Nowe posty

xx Problem ze sterownikami. (5)
2024-04-13, 21:25:16
xx Instalacja xfce4 (2)
2024-04-13, 16:20:17
xx Serie kompilacji bez instalacji dla “emerge” w Gentoo (2)
2024-04-08, 18:40:04
xx Plasma 6 w Neonie ssie trochę mniej ... (17)
2024-04-05, 10:03:46
xx Problem z Linux Lite po instalacji (3)
2024-04-03, 14:23:40
xx Jak właczyć num locka przy starcie systemu debian 12? (12)
2024-04-02, 17:43:54
xx Brak dźwieku w systemie. (5)
2024-04-02, 16:13:41
xx Dystrybucja pod HP Omen (7)
2024-03-29, 11:33:05
xx [Poradnik] Wyszukiwanie Sterowników (2)
2024-03-27, 21:08:23
xx Ile pingwinów? (1)
2024-03-27, 08:59:24

Autor Wątek: skrypt wysyłający sms z modemu gsm  (Przeczytany 17083 razy)

pelikan

  • Gość
skrypt wysyłający sms z modemu gsm
« dnia: 2013-05-16, 10:48:03 »
Witam,
Od razu powiem, że z programowanie to nie jest moja pasja. Chciałbym jednak zbudować skrypt który wysyłałby smsy poprzez modem gsm.
Bardzo ułatwiłoby mi to moją pracę, gdyż obecnie wykonuje to za pomocą komputera ale każdego smsa wysyłam "ręcznie". W smsie ma być wysyłana informacja pobrana z pliku tekstowego
o strukturze:
112,20130515,18050,12121214,178787879,"52222222222222222222222776","136263644444444444444444003","Nazwa nadawcy","Nazwa odbiorcy",0,23432343,"Tresc wiadomosci","","","840569434589345834","","59487567060547603","578670856087340670"
112,20130515,18050,12121214,178787879,"52222222222222222222222776","136263644444444444444444003","Nazwa nadawcy","Nazwa odbiorcy",0,23432343,"Tresc wiadomosci","","","840569434589345834","","59487567060547603","578670856087340670"
113,20130515,37900,14645747,189809089,"11626364905694055080000002","889898980898080808080808001","Nazwa nadawcy","Nazwa odbiorcy",0,64565464,"Tresc wiadomości","","","91","|||G||31","","5"
113,20130515,37900,14645747,189809089,"11626364905694055080000002","889898980898080808080808001","Nazwa nadawcy","Nazwa odbiorcy",0,64565464,"Tresc wiadomości","","","91","|||G||31","","5"
Jak widać separatorem jest przecinek. Ja chciałbym wysyłać następującą treść z pola 3 (w pierwszej linii to 18050) oraz treść z pola 11(Treść wiadomości), z tym że przykłądowa wartość z pola 18050 powinna być przerobiona na 180,50zł.
SMS z takimi informacjami chciałbym aby został wysłany na nr tel pobrany z drugiego pliku tekstowego o takiej strukturze:

Jan Kowalski,136263644444444444444444003,634673243
Anna Nowak,11626364905694055080000002,691625987
Informacja z pierwszej i drugiej linii powinna być wysłana do Jana Kowalskiego ponieważ  136263644444444444444444003 to jego unikalny identyfikator, który wystąpił w polu 7 pierwszej i drugiej linii
Informacja z trzeciej i czwartej linii powinna być wysłana do Anny Nowak ponieważ 11626364905694055080000002 to jej unikalny identyfikator, który wystąpił w polu 6 trzeciej i czwartej linii.

Założenia są takie:
- mogą wystąpić linie w pierwszym pliku, które nie będą wysyłane ponieważ w pliku drugim nie będzie wpisanej osoby o identyfikatorze który wystąpił w polu 6 lub 7.
- skrypt powinien np co 30 min sprawdzać czy w określonej lokalizacji "pojawił" się pierwszy plik a po jego przeanalizowaniu (wysłaniu smsów do określonych osób) powinien zostać skasowany.

Może ktoś na początek podpowie jak się do tego zabrać. Jak dla mnie temat ambity ale przy tej okazji będe się mógł czegoś nowego nauczyć.

alvaro

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #1 dnia: 2013-05-17, 13:47:53 »
Najpierw trzeba w jakiś sensowny sposób wydobyć te dane.

Załóżmy, że dane z pierwszego pliku znajdują się w pliku 1.txt a dane z drugiego pliku w pliku 2.txt.
Wtedy za pomocą następującego polecenia można dojść do jakiejś w miarę sensownej postaci:

# join -t , <(sed -r -e "/^[[:blank:]]*$/d" 2.txt | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" 1.txt | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | awk -F, '{print $1 "," $3 "," $4}' | sed -r -e "s/^([^,]*),([[:digit:]]*)([[:digit:]]{2}),([^,]*)$/\\1,\\4\\: \\2.\\3 PLN/"
691625987,Tresc wiadomości: 379.00 PLN
691625987,Tresc wiadomości: 379.00 PLN
634673243,Tresc wiadomosci: 180.50 PLN
634673243,Tresc wiadomosci: 180.50 PLN
Pokrótce opiszę, co to robi:
- na początku za pomocą sed usuwam puste linie a następnie z pierwszego pliku usuwam znaki cudzysłowów znajdujące się na początku/końcu linii oraz w obok separatora (przecinka)
- numeruję linie za pomocą nl - dzięki temu będę mógł później korzystać z uniq do usunięcia zdublowanych wpisów (np. w sytuacji gdy w jednej linii kolumny nr 6 i 7 są identyczne i mają odpowiednik w drugim pliku)
- za pomocą awk wybieram interesujące mnie kolumny, robiąc przy tym mały trick - dubluje liczbę wpisów zakładając przy tym, że raz poprawnym identyfikatorem jest wpis z kolumny nr 6 a drugi raz, że z kolumny nr 7
- łączę dane z obydwu plików za pomocą join po pierwszej kolumnie - identyfikatorze
- usuwam pierwszą kolumnę z identyfikatorem za pomocą cut
- usuwam zbędne kolumny za pomocą awk - zostają trzy: numer, liczba (z trzeciej początkowej kolumny) i wiadomość
- za pomocą sed przestawiam kolumny i formatuję tekst robiąc mały trick z liczą - sprowadzam ją do postaci "180.50 PLN" (zamiast "18000")

Uwagi:
- treść wiadomości pobieram z 12 a nie 11 początkowej kolumny; jest to spowodowane tym, że liczba poprzedzająca treść wiadomości używa przecinka (zamiast np. kropki) jako separatora dziesiętnego przez co powstaje dodatkowa kolumna
- jako, że w trakcie operacji na początek dodaje dodatkowo kolumnę z liczbą to numery pozostałych kolumn zwiększają się o jeden
- treść wiadomości od liczby z trzeciej początkowej kolumny oddzielam za pomocą ": "
- powyższe polecenie nie modyfikuje plików

Gotowe skrypty

getmsg.bash sprowadza dane do sensownej postaci.
Pobiera dwa argumenty - nazwę pierwszego pliku z wiadomościami i nazwę drugiego pliku z kontaktami.
Wypisuje odpowiednio sformatowane dane na wyjściu.

#!/bin/env bash

if [ "$#" -eq 2 ]; then
  if [ ! -f "$1" ]; then echo "Arg 1 should be filename1 (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename2 (contacts)." >&2; exit 1; fi
  join -t , <(sed -r -e "/^[[:blank:]]*$/d" "$2" | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" "$1" | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | awk -F, '{print $1 "," $3 "," $4}' | sed -r -e "s/^([^,]*),([[:digit:]]*)([[:digit:]]{2}),([^,]*)$/\\1,\\4\\: \\2.\\3 PLN/"
else
  echo "Needs 2 args: filename1 (messages) and filename2 (contacts)." >&2
fi
http://wklej.org/hash/bb704fef253/

# ./getmsg.bash 1.txt 2.txt 
691625987,Tresc wiadomości: 379.00 PLN
691625987,Tresc wiadomości: 379.00 PLN
634673243,Tresc wiadomosci: 180.50 PLN
634673243,Tresc wiadomosci: 180.50 PLN
sendmsg.bash wysyła dane za pomocą sendsms.bash korzystając z getmsg.bash.
Pobiera dwa argumenty - nazwę pierwszego pliku z wiadomościami i nazwę drugiego pliku z kontaktami.
Wysyła wiadomość za pomocą sendsms.bash.

#!/bin/env bash

getmsg=$(dirname "$0")/getmsg.bash
sendsms=$(dirname "$0")/sendsms.bash

if [ "$#" -eq 2 ]; then
  if [ ! -f "$1" ]; then echo "Arg 1 should be filename1 (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename2 (contacts)." >&2; exit 1; fi
  $getmsg $1 $2 | while IFS=, read -r number message; do $sendsms "$number" <<< "$message"; done
else
  echo "Needs 2 args: filename1 (messages) and filename2 (contacts)." >&2
fi
http://wklej.org/hash/f7c375f5328/

# ./sendmsg.bash 1.txt 2.txt 
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
dosms.bash czyta wiadomości w podanym katalogu i wysyła dane za pomocą sendsms.bash.
Pobiera dwa argumenty - nazwę katalogu z plikami z wiadomości i nazwę pliku z kontaktami.
Czyta dane z plików w podanych katalogu, wysyła wiadomość za pomocą sendsms.bash i usuwa pliku.

#!/bin/env bash

sendmsg=$(dirname "$0")/sendmsg.bash

if [ "$#" -eq 2 ]; then
  if [ ! -d "$1" ]; then echo "Arg 1 should be dirname (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename (contacts)." >&2; exit 1; fi
 
  shopt -s globstar;
  for file in "$1"/**; do [[ -f $file ]] || continue;
    echo "Sending messages from file '$file'." >&2;
    $sendmsg $file $2
    rm $file
  done

else
  echo "Needs 2 args: dirname (messages) and filename (contacts)." >&2
fi
Uwaga! Szuka plików w katalogu i jego podkatalogach.
Żeby to zmienić (aby skrypt szukał plików tylko i wyłącznie w jednym katalogu bez jego podkatalogów) należy zamienić linię:
for file in "$1"/**; do [[ -f $file ]] || continue;
na:
for file in "$1"/*; do [[ -f $file ]] || continue;
Innymi słowy: zamienić dwie gwiazdki na jedną.

http://wklej.org/hash/70405179d16/

# ./dosms.bash msg.d 2.txt 
Sending messages from file 'msg.d/1.txt'.
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
Sending messages from file 'msg.d/2.txt'.
Number: 691625987
Message: Tresc wiadomości 23: 379.00 PLN
---
Number: 691625987
Message: Tresc wiadomości 24: 379.00 PLN
---
Number: 634673243
Message: Tresc wiadomosci 21: 180.50 PLN
---
Number: 634673243
Message: Tresc wiadomosci 22: 180.50 PLN
---
Sending messages from file 'msg.d/3.txt'.
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
sendsms.bash odpowiada za wysyłanie SMSów.
Pobiera numery telefonów za argumenty.
Na standardowym wejściu oczekuje treści wiadomości.
Wysyła wiadomość podaną na standardowym wejściu na numery telefonów podanych jako argumenty.

#!/bin/env bash

if [ "$#" -gt 0 ]; then
 
  read message
 
  for number in "$@"
  do
    echo "Number: $number"
    echo "Message: $message"
    echo "---"
    #echo "$message" | gammu sendsms TEXT "$number"
  done

else
  echo "Need 1 arg: number. Expect message on stdin." >&2
fi
Tak naprawdę sendsms.bash nie wysyła wiadomości SMS tylko wypisuje je na standardowym wyjściu.
Można to zmienić chociażby poprzez konfigurację Gammu i odkomentowanie linii:
#echo "$message" | gammu sendsms TEXT "$number"
http://wklej.org/hash/b301bc8e6a2/

# echo "test" | ./sendsms.bash 123456789
Number: 123456789
Message: test
---
Konfiguracja

Wysyłanie SMS

Jak już wspomniałem wcześniej skrypt sendsms.bash nie wysyła tak naprawdę SMSów, ale stanowi zalążek bo stworzenie takiego skryptu. W przypadku korzystania z Gammu powinno wystarczyć praktycznie tylko odkomentowanie jednej linii.

Aby wysyłanie SMSów w systemie rzeczywiście działało należy skonfigurować połączenie at czy blueat z takim programem jak Gammu.
Szczegóły konfiguracji zależą od modelu telefonu/modemu. Lista wspieranych urządzeń znajduje się na stronie projektu wammu. Wammu jest nakładką graficzną na Gammu.
Informacje na temat wysyłania SMS za pomocą Gammu można bez problemu znaleźć w Internecie.

Uruchamianie

Aby wywoływać skrypt co określony czas (np. 30 minut) najlepiej posłużyć się cron/crontab.

# crontab -e
*/30 * * * * /sciezka/do/skryptu
Być może warto rozważyć dodanie ścieżki do katalogu ze skryptami do zmiennej PATH - patrz plik ~/.bash_profile.

alvaro

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #2 dnia: 2013-05-18, 06:05:56 »
Jeśli zależy nam na wysłaniu SMS w ustalonej początkowej kolejności to należy dodać sort (sort -t , -k 2) przed ostatnim awk:
# join -t , <(sed -r -e "/^[[:blank:]]*$/d" 2.txt | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" msg.d/2.txt | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | sed -r -e "s/^([^,]*),([[:digit:]]*)([[:digit:]]{2}),([^,]*)$/\\1,\\4\\: \\2.\\3 PLN/"
634673243,Tresc wiadomosci 21: 180.50 PLN
634673243,Tresc wiadomosci 22: 180.50 PLN
691625987,Tresc wiadomości 23: 379.00 PLN
691625987,Tresc wiadomości 24: 379.00 PLN
Spowoduje to posortowanie linii wg początkowej kolejności - kolumna nr 2 (pozycja po połączeniu danych z obydwu plików) została stworzona przez program nl, który numeruje linie.

Wtedy getmsg.bash wyglądałby tak:
#!/bin/env bash

if [ "$#" -eq 2 ]; then
  if [ ! -f "$1" ]; then echo "Arg 1 should be filename1 (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename2 (contacts)." >&2; exit 1; fi
  join -t , <(sed -r -e "/^[[:blank:]]*$/d" "$2" | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" "$1" | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | sed -r -e "s/^([^,]*),([[:digit:]]*)([[:digit:]]{2}),([^,]*)$/\\1,\\4\\: \\2.\\3 PLN/"
else
  echo "Needs 2 args: filename1 (messages) and filename2 (contacts)." >&2
fi
http://wklej.org/hash/c71c197da24/

pelikan

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #3 dnia: 2013-07-05, 15:00:23 »
Nie wiem dlaczego ale wiadomość gdzie jest 379.00 PLN wysyła się tak:

Number: 684??????
Message: 37900,Tresc wiadomości
---
If you want break, press Ctrl+C...
Sending SMS 1/1....waiting for network answer..OK, message reference=74
a dla wiadomosci gdzie jest 180.50 PLN wysyłą się tak:

Number: 686??????
Message: Tresc wiadomosci: 180.50 PLN
---
If you want break, press Ctrl+C...
Sending SMS 1/1....waiting for network answer..OK, message reference=76
Czyli dla wiadomości z kwotą 379.00 PLN cos jest nie tak. Nie potrafię sam wymyśleć co.
Skrypt getmsg.bash daje taki efekt:

684??????,37900,Tresc wiadomości
684??????,37900,Tresc wiadomości
686??????,Tresc wiadomosci: 180.50 PLN
696??????,Tresc wiadomosci: 180.50 PLN

alvaro

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #4 dnia: 2013-07-05, 19:41:09 »
Ciężko mi odnaleźć przyczynę nie znając szczegółów (dokładnej zawartości plików).

W skrypcie było trochę przestawiania kolumn. Wystarczy chociażby jeden dodatkowy przecinek (w tekście czy użyty jako separator dziesiętny) i już numeracja pól się zmienia.

Mogła się także gdzieś wkraść spacja i dlatego ostatni sed nie zadziałał.
join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^ *//;s/ *$//;s/ *, */,/g" 2.txt | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^ *//;s/ *$//;s/ *, */,/g;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" 1.txt | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | sed -r -e "s/^([^,]*),,/\\1,000,/;s/^([^,]*),([[:digit:]]),/\\1,00\\2,/;s/^([^,]*),([[:digit:]]{2}),/\\1,0\\2,/;s/^([^,]*),([[:digit:]]*)([[:digit:]]{2}),([^,]*)$/\\1,\\4\\: \\2.\\3 PLN/"
Bez poznania szczegółów (zawartości plików wejściowych) mogę tylko gdybać.

pelikan

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #5 dnia: 2013-07-16, 11:41:56 »
Tak wyglada plik wejsciowy:
112,20130515,18050,12121214,178787879,"52222222222222222222222776","136263644444444444444444003","Nazwa nadawcy","Nazwa odbiorcy",0,23432343,"Tresc wiadomosci","","","840569434589345834","","59487567060547603","578670856087340670"
112,20130515,18050,12121214,178787879,"52222222222222222222222776","136263644444444444444444003","Nazwa nadawcy","Nazwa odbiorcy",0,23432343,"Tresc wiadomosci","","","840569434589345834","","59487567060547603","578670856087340670"
113,20130515,37900,14645747,189809089,"11626364905694055080000002","889898980898080808080808001","Nazwa nadawcy","Nazwa odbiorcy",0,64565464,"Tresc wiadomości","","","91","|||G||31","","5"
113,20130515,37900,14645747,189809089,"11626364905694055080000002","889898980898080808080808001","Nazwa nadawcy","Nazwa odbiorcy",0,64565464,"Tresc wiadomości","","","91","|||G||31","","5"

alvaro

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #6 dnia: 2013-07-18, 20:40:15 »
Nie widzę, żeby podany przez Pana plik wejściowy różnił się od tego zamieszczonego za pierwszym razem.
U mnie dla podanych danych wejściowych skrypt zwraca oczekiwane wyniki:
# cat 1.txt 
112,20130515,18050,12121214,178787879,"52222222222222222222222776","136263644444444444444444003","Nazwa nadawcy","Nazwa odbiorcy",0,23432343,"Tresc wiadomosci","","","840569434589345834","","59487567060547603","578670856087340670"
112,20130515,18050,12121214,178787879,"52222222222222222222222776","136263644444444444444444003","Nazwa nadawcy","Nazwa odbiorcy",0,23432343,"Tresc wiadomosci","","","840569434589345834","","59487567060547603","578670856087340670"
113,20130515,37900,14645747,189809089,"11626364905694055080000002","889898980898080808080808001","Nazwa nadawcy","Nazwa odbiorcy",0,64565464,"Tresc wiadomości","","","91","|||G||31","","5"
113,20130515,37900,14645747,189809089,"11626364905694055080000002","889898980898080808080808001","Nazwa nadawcy","Nazwa odbiorcy",0,64565464,"Tresc wiadomości","","","91","|||G||31","","5"
# cat 2.txt
Jan Kowalski,136263644444444444444444003,634673243
Anna Nowak,11626364905694055080000002,691625987
# ./getmsg.bash 1.txt 2.txt
634673243,Tresc wiadomosci: 180.50 PLN
634673243,Tresc wiadomosci: 180.50 PLN
691625987,Tresc wiadomości: 379.00 PLN
691625987,Tresc wiadomości: 379.00 PLN
# ./sendmsg.bash 1.txt 2.txt
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
Number: 634673243
Message: Tresc wiadomosci: 180.50 PLN
---
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
Number: 691625987
Message: Tresc wiadomości: 379.00 PLN
---
wklejka

Załączam jeszcze poprawioną wersję getmsg.bash, która powinna być bardziej odporna na błędy (jakieś niepotrzebne spacje czy kwotę mniejszą od 1 zł):
#!/bin/env bash

if [ "$#" -eq 2 ]; then
  if [ ! -f "$1" ]; then echo "Arg 1 should be filename1 (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename2 (contacts)." >&2; exit 1; fi
  join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" "$2" | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" "$1" | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | sed -r -e "s/^([^,]*),,/\\1,000,/;s/^([^,]*),([[:digit:]]),/\\1,00\\2,/;s/^([^,]*),([[:digit:]]{2}),/\\1,0\\2,/;s/^([^,]*),([[:digit:]]*)([[:digit:]]{2}),([^,]*)$/\\1,\\4\\: \\2.\\3 PLN/"
else
  echo "Needs 2 args: filename1 (messages) and filename2 (contacts)." >&2
fi
wklejka

Wyniki, które zamieścił Pan w czwartym poście w tym wątku mogą sugerować, że problemem jest ostatni sed.
Bez niego skrypt zwracałby wyniki w następującej postaci:
# join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 2.txt | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" 1.txt | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}'
634673243,18050,Tresc wiadomosci
634673243,18050,Tresc wiadomosci
691625987,37900,Tresc wiadomości
691625987,37900,Tresc wiadomości
W tym momencie pozostaje kwestia sformatowania kwoty i umieszczenia jej w odpowiednim miejscu (np. za treścią wiadomości), np.:
# join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 2.txt | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" 1.txt | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | awk -F, '{print $1 "," $3 ": " $2 " gr"}'
634673243,Tresc wiadomosci: 18050 gr
634673243,Tresc wiadomosci: 18050 gr
691625987,Tresc wiadomości: 37900 gr
691625987,Tresc wiadomości: 37900 gr
albo:
# join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 2.txt | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" 1.txt | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | awk -F, '{print $1 "," $3 ": " $2/100 " PLN"}'
634673243,Tresc wiadomosci: 180.5 PLN
634673243,Tresc wiadomosci: 180.5 PLN
691625987,Tresc wiadomości: 379 PLN
691625987,Tresc wiadomości: 379 PLN
czy:
# join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 2.txt | awk -F, '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g;s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" 1.txt | nl -w1 -s, | awk -F, '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | awk -F, '{printf("%s,%s: %.2f PLN\\n", $1, $3, $2/100)}'
634673243,Tresc wiadomosci: 180.50 PLN
634673243,Tresc wiadomosci: 180.50 PLN
691625987,Tresc wiadomości: 379.00 PLN
691625987,Tresc wiadomości: 379.00 PLN

pelikan

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #7 dnia: 2013-08-26, 12:29:21 »
Mam jeszcze jeden problem z tymi skryptami. W polach 8 i 9 pliku wejsciowego ("nazwa nadawcy" oraz "nazwa odbiorcy" czasami występują przecinki i wtedy skrypt traktuje je jako separatory. Cz da się jakosć na samym początku usunąć potencjalne przecinki w polach 8 i 9.

alvaro

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #8 dnia: 2013-08-26, 17:54:59 »
Istnieje rozszerzenie GNU Awk 4 pozwalające na zdefiniowanie wzorca dla pola zamiast separatora:
# gawk -vFPAT='[^,]*|"[^"]*"' '{print $8 "; " $9}' 1g.txt 
"Nazwa nadawcy"; "Nazwa odbiorcy"
"Nazwa, nadawcy"; "Nazwa odbiorcy"
"Nazwa nadawcy"; "Nazwa, odbiorcy"
"Nazwa, nadawcy"; "Nazwa, odbiorcy"
Żeby z tego korzystać należy się wcześniej upewnić, że rzeczywiście posiada się czwartą wersję GNU Awk:
# gawk --version
GNU Awk 4.0.1
Copyright (C) 1989, 1991-2012 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
Korzystając z tej sztuczki można przetwarzać wiadomości w następujący sposób:
# join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 2.txt | awk -vFPAT='[^,]*|"[^"]*"' '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 1.txt | nl -w1 -s, | awk -vFPAT='[^,]*|"[^"]*"' '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | sed -r -e "s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | awk -F, '{printf("%s,%s: %.2f PLN\\n", $1, $3, $2/100)}'
634673243,Tresc wiadomosci: 180.50 PLN
634673243,Tresc wiadomosci: 180.50 PLN
691625987,Tresc wiadomości: 379.00 PLN
691625987,Tresc wiadomości: 379.00 PLN
Nasz getmsg.bash mógłby wyglądać następująco:
#!/bin/env bash

if [ "$#" -eq 2 ]; then
  if [ ! -f "$1" ]; then echo "Arg 1 should be filename1 (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename2 (contacts)." >&2; exit 1; fi
  join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" "$2" | awk -vFPAT='[^,]*|"[^"]*"' '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" "$1" | nl -w1 -s, | awk -vFPAT='[^,]*|"[^"]*"' '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | sed -r -e "s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | awk -F, '{print $1 "," $3 "," $4}' | awk -F, '{printf("%s,%s: %.2f PLN\\n", $1, $3, $2/100)}'
else
  echo "Needs 2 args: filename1 (messages) and filename2 (contacts)." >&2
fi
wklejka

pelikan

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #9 dnia: 2013-08-27, 10:49:26 »
chyba nie mam wcale gawk, mam tylko awk na debianie. Można to doinstalować?
root@debianSMS:/usr/local/bin/bankomatsms# gawk
-bash: gawk: nie znaleziono polecenia
root@debianSMS:/usr/local/bin/bankomatsms# gawk --version
-bash: gawk: nie znaleziono polecenia
root@debianSMS:/usr/local/bin/bankomatsms# awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan

compiled limits:
max NF             32767
sprintf buffer      1020
root@debianSMS:/usr/local/bin/bankomatsms#

alvaro

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #10 dnia: 2013-08-27, 12:34:15 »
W repozytoriach Debiana znajduje się pakiet gawk.

Wystarczy go zainstalować:
# apt-get install gawk gawk-doc
Oczywiście powyższe polecenie wydajemy z poziomu roota.

Zostaje kwestia tego co kryje się pod komendą awk:
# test -L "$(which awk)" && readlink -f "$(which awk)" || echo "$(which awk)"
/bin/gawk
W moim przypadku /usr/awk to dowiązanie symboliczne do /usr/gawk.

Być może pod Debianem jest to rozwiązane za pomocą alternatives.

Zamiast bawić się w dowiazania symboliczne można zmienić w naszym skrypcie wywołania awk na gawk.

Poprawiony getmsg.bash:
#!/bin/env bash

if [ "$#" -eq 2 ]; then
  if [ ! -f "$1" ]; then echo "Arg 1 should be filename1 (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename2 (contacts)." >&2; exit 1; fi
  join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" "$2" | gawk -vFPAT='[^,]*|"[^"]*"' '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" "$1" | nl -w1 -s, | gawk -vFPAT='[^,]*|"[^"]*"' '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | sed -r -e "s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | gawk -F, '{print $1 "," $3 "," $4}' | gawk -F, '{printf("%s,%s: %.2f PLN\\n", $1, $3, $2/100)}'
else
  echo "Needs 2 args: filename1 (messages) and filename2 (contacts)." >&2
fi
wklejka

Jeszcze taka drobna uwaga: co prawda dla uproszczenia za znak zachęty (command prompt) zawsze podawałem "# " jednak nie chodziło mi o to, żeby każde z poleceń wykonywać z poziomu roota. Skrypt można wykonywać z poziomu nieuprzywilejowanego użytkownika.
$ join -t , <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 2.txt | gawk -vFPAT='[^,]*|"[^"]*"' '{print $2 "," $3}' | sort) <(sed -r -e "/^[[:blank:]]*$/d;s/^[[:blank:]]*//;s/[[:blank:]]*$//;s/[[:blank:]]*,[[:blank:]]*/,/g" 1.txt | nl -w1 -s, | gawk -vFPAT='[^,]*|"[^"]*"' '{print $7 "," $1 "," $4 "," $13 "\\n" $8 "," $1 "," $4 "," $13}' | sed -r -e "s/^\\"//;s/\\"$//;s/\\",/,/g;s/,\\"/,/g" | uniq | sort) | cut -d "," -f 2- | uniq | sort -t , -k 2 | gawk -F, '{print $1 "," $3 "," $4}' | gawk -F, '{printf("%s,%s: %.2f PLN\\n", $1, $3, $2/100)}'
634673243,Tresc wiadomosci: 180.50 PLN
634673243,Tresc wiadomosci: 180.50 PLN
691625987,Tresc wiadomości: 379.00 PLN
691625987,Tresc wiadomości: 379.00 PLN

pelikan

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #11 dnia: 2013-09-03, 11:28:11 »
Wszystko juz fajnie śmiga. Czasami (1 na 100 przypadków) zdaży się że sms nie jest wysłany (mozliwy problem z zasięgiem). Dlatego chciałbym skonfigurować logi z informacjami co wysyłał gammu i z jakim skutkiem. Czy jest wogóle taka możliwość.

alvaro

  • Gość
skrypt wysyłający sms z modemu gsm
« Odpowiedź #12 dnia: 2013-09-04, 08:35:00 »
Logi

Nie widzę problemu żeby zapisywać logi z poziomu np. sendsms.bash czy sendmsg.bash.

sendmsg.bash:
#!/bin/env bash

getmsg=$(dirname "$0")/getmsg.bash
sendsms=$(dirname "$0")/sendsms.bash

logfile="/var/logs/sendsms/logfile.txt"
default="/etc/default/sendsms"
[ -f "$default" ] && [ -r "$default" ] && . "$default"

if [ "$#" -eq 2 ]; then
  if [ ! -f "$1" ]; then echo "Arg 1 should be filename1 (messages)." >&2; exit 1; fi
  if [ ! -f "$2" ]; then echo "Arg 2 should be filename2 (contacts)." >&2; exit 1; fi
  $getmsg $1 $2 | while IFS=, read -r number message; do $sendsms "$number" <<< "$message" >> "$logfile" 2>&1; done
else
  echo "Needs 2 args: filename1 (messages) and filename2 (contacts)." >&2
fi
/etc/default/sendsms:
logfile="/var/log/sendsms.log"
SMS Daemon

Zamiast korzystać ze zwykłego gammu (pakiet gammu) można korzystać z gammu-smsd-inject znajdującego się w Debianie w pakiecie gammu-smsd.

W tym celu po zainstalowaniu pakietu:
apt-get install gammu-smsd
należy odpowiednio skonfigurować SMSD (SMS Daemon).

Istnieje możliwość podania pliku gdzie będą zapisywane logi (LogFile) czy maksymalnej liczby powtórzeń w przypadku niepowodzenia wysłania wiadomości (MaxRetries). Po więcej szczegółów odsyłam do dokumentacji.

Należy się upewnić, że daemon gammu-smsd jest uruchomiony:
service gammu-smsd status
Jeśli tak nie jest należy go uruchomić:
service gammu-smsd start
Korzystanie z SMSD niesie z sobą szereg korzyści. Jedną z nich jest wspomniana już możliwość powtórzenia próby wysłania wiadomości SMS w przypadku niepowodzenia operacji.

sendsms.bash:
#!/bin/env bash

if [ "$#" -gt 0 ]; then
 
  read message
 
  for number in "$@"
  do
    echo "Number: $number"
    echo "Message: $message"
    echo "$message" | gammu-smsd-inject TEXT "$number"
    echo "---"
  done

else
  echo "Need 1 arg: number. Expect message on stdin." >&2
fi
SMS-Gateway

Alternatywą do wysyłania SMSów korzystając bezpośrednio z telefonu/modemu GSM są usługi typu SMS-Gateway.
W przypadku wysyłania większej liczby wiadomości radzę rozważyć korzystanie z takich usług jak np. Clickatell, BulkSMS czy ViaNett. Można z nich korzystać za pomocą przyjaznych API (Clickatell SMS APIs, BULKSMS SMS APIs, Via Nett Developer APIs). Istnieją także gotowe biblioteki pozwalające na łatwe korzystanie z takich usług z poziomu skryptów.