SMSバジェットニュースレター

すべてのhabrozhitelへのご挨拶!



もちろん、SMSメッセージの送信に関するなめられたトピックですが、彼らが言うように:「たくさん-少しではない」。 どういうわけか、私を常に悩ましているのは彼女だったのです。一部の優秀な人や他の人は、予算メッセージの実装に参加するように(たとえば、アドバイスを伴って)私に頼みます。 したがって、蓄積された財を消滅させないために、ここに置いておきます。突然、それは誰かに役立ちます...



だから、と...通常のコンピューターとNTファミリーの軸に基づくすべての実装オプションを省略します。 そして、すぐに「自律」システムに渡します。



Arduinoはこの方向で何を誇ることができますか? すぐにお答えしますが、ITは機能しますが、以下で説明するニュアンスがあります。 一般的に、中国語版のarduino 2560(ほぼすべてのラインが試されました)と2つの追加モジュール-W5100ネットワーク(最も安定したバージョン)とGSM SIM 900があります。この全体は次のようになります。



画像



タスクは次のとおりです。

-デバイスはhttp経由で通信できる必要があります

-メッセージを送信

-結果をJSON形式で出力する



Googleはすべての必要な情報を共有し、出力は次のコードです。



スケッチ
#include <SPI.h> #include <Ethernet.h> #include <String.h> #include "SIM900.h" #include <SoftwareSerial.h> #include "sms.h" #include <LiquidCrystal_I2C.h> #include <Wire.h> byte mac[] = { 0x90, 0xA2, 0x00, 0x00, 0x00, 0x01 }; IPAddress ip(192,168,34,139); EthernetServer server(80); char char_in = 0; String HTTP_req; SMSGSM sms; boolean started=false; bool power = false; LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); void setup() { Serial.begin(9600); lcd.begin(16,2); lcd.setCursor(0,0); lcd.print("INIT GSM..."); lcd.setCursor(0,1); lcd.print("WAIT!!!"); //powerUp(); gsm.forceON(); if (gsm.begin(4800)) { Serial.println("\nstatus=READY"); lcd.clear(); lcd.setCursor(0,0); lcd.print("READY"); started=true; } else { Serial.println("\nstatus=IDLE"); lcd.clear(); lcd.setCursor(0,0); lcd.print("IDLE"); } Ethernet.begin(mac, ip); server.begin(); } void software_reset() { asm volatile (" jmp 0"); } void loop() { EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char_in = client.read(); // HTTP_req += char_in; if (char_in == '\n') { Serial.println(HTTP_req); if(HTTP_req.indexOf("GET /res") >= 0) { reset_processing(&HTTP_req, &client); break; } if(HTTP_req.indexOf("GET /sms") >= 0) { sms_processing(&HTTP_req, &client); break; } if(HTTP_req.indexOf("GET /test") >= 0) { test_processing(&HTTP_req, &client); break; } else { client_header(&client); break; } } } } HTTP_req = ""; client.stop(); } if(power) { delay(1000); software_reset(); } } char* string2char(String command) { if(command.length()!=0){ char *p = const_cast<char*>(command.c_str()); return p; } } void parse_data(String *data) { data->replace("GET /sms/",""); data->replace("GET /test/", ""); int lastPost = data->indexOf("\r"); *data = data->substring(0, lastPost); data->replace(" HTTP/1.1", ""); data->replace(" HTTP/1.0", ""); data->trim(); } // explode String request_value(String *data, char separator, int index) { int found = 0; int strIndex[] = {0, -1}; int maxIndex = data->length()-1; for(int i=0; i<=maxIndex && found<=index; i++) { if(data->charAt(i)==separator || i==maxIndex) { found++; strIndex[0] = strIndex[1]+1; strIndex[1] = (i == maxIndex) ? i+1 : i; } } return found>index ? data->substring(strIndex[0], strIndex[1]) : ""; } bool gsm_status() { bool result = false; switch(gsm.CheckRegistration()) { case 1: result = true; break; default: break; } return result; } bool gsm_send(char *number_str, char *message_str) { bool result = false; switch(sms.SendSMS(number_str, message_str)) { case 1: result = true; break; default: break; } return result; } void reset_processing(String *data, EthernetClient *cl) { client_header(cl); cl->println("\{\"error\": 0, \"message\": \"restarting...\"\}"); power = true; } void test_processing(String *data, EthernetClient *cl) { parse_data(data); if(started) { client_header(cl); cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":0" + ",\"message\":\"test success\"\}"); } } void sms_processing(String *data, EthernetClient *cl) { parse_data(data); if(started) { if (gsm_send(string2char(request_value(data, '/', 1)), string2char(request_value(data, '/', 2)))) { client_header(cl); cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":0" + ",\"message\":\"success\"\}"); } else { if(!gsm_status()) { client_header(cl); cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":2" + ",\"message\":\"gsm not registered\"\}"); power = true; } else { client_header(cl); cl->println("\{\"id\":" + request_value(data, '/',0) + ",\"error\":1" + ",\"message\":\"fail\"\}"); } } } } void client_header(EthernetClient *cl) { cl->println("HTTP/1.1 200 OK"); cl->println("Content-Type: text/plain"); cl->println("Connection: close"); cl->println(); }
      
      









記入し、箱に詰めます。 それは美しく見えるようで、私たちは良い人に与えます。



画像



コードで何が起こったのか:

-シンプルなhttpを上げました

-単純なgetを処理する

-受信したデータをシリアル経由でSIM 900に送信する

-「JSON」を使用して回答



そして、ここには大きなニュアンスがあります。賢い人は、このデバイスを介してメッセージのパケットをすぐに送信する方法を学ぶために、ある種のサービスを実装するタスクに直面していますが、これは私の問題ではありません。 本番環境では、デバイスは十分に動作しました。



私たちは能力を構築しています...タスクはまったく同じです。繰り返しは学習の母です。 スマートな人々は、以前のデバイスを操作するためのクールなサービス、キュー、履歴、その他の有用性をすでに作成しています。



したがって、ラズベリーパイを手に入れ、同じSIM 900モジュール(LinuxはUSB経由で3Gモデムで正常に動作するため、実験のためにのみ取られました)と3gモデムhuawei e-line自体



画像



繰り返しますが、Googleに必要な質問をし、結果を読んで、実装言語を決定します-Python-素早く、簡単に、確実に...



台本
 import serial, time from flask import Flask import RPi.GPIO as GPIO app = Flask(__name__) def sim900_on(): gsm = serial.Serial('/dev/ttyAMA0', 115200, timeout=1) gsm.write('ATZ\r') time.sleep(0.05) abort_after = 5 start = time.time() output = "" while True: output = output + gsm.readline() if 'OK' in output: gsm.close() return True delta = time.time() - start if delta >= abort_after: gsm.close() break #GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) GPIO.setup(11, GPIO.OUT) GPIO.output(11, True) time.sleep(1.2) GPIO.output(11, False) return False def gsm_send(id, port, phone, msg): delay = False if 'AMA' in port: delay = True msg = msg.replace('\\n', '\n') msg = msg.replace('\s', ' ') gsm = serial.Serial('/dev/tty%s' % port, 115200, timeout=1) gsm.write('ATZ\r') if delay: time.sleep(0.05) gsm.write('AT+CMGF=1\r\n') if delay: time.sleep(0.05) gsm.write('AT+CMGS="%s"\r\n' % phone) if delay: time.sleep(0.05) gsm.write(msg + '\r\n') if delay: time.sleep(0.05) gsm.write(chr(26)) if delay: time.sleep(0.05) abort_after = 15 start = time.time() output = "" while True: output = output + gsm.readline() #print output if '+CMGS:' in output: print output gsm.close() return '{"id":%s,"error":0,"message":"success", "raw":"%s"}' % (id, output) if 'ERROR' in output: print output gsm.close() return '{"id":%s,"error":0,"message":"fail", "raw":"%s"}' % (id, output) delta = time.time() - start if delta >= abort_after: gsm.close() return '{"id":%s,"error":1,"message":"timeout", "raw":"%s"}' % (id, output) @app.route('/sms/<id>/<port>/<phone>/<msg>',methods=['GET']) def get_data(id, port, phone, msg): return gsm_send(id, port, phone, msg) @app.route('/',methods=['GET']) def index(): return "Hello World" if __name__ == "__main__": sim900_on() app.run(host="0.0.0.0", port=8080, threaded=True)
      
      









Pythonにフィードを送り、「start-stop-daemon」の助けを借りて起動し、フレンドリーな外観を与え、親切な人々に与えます...



画像



ほぼ1対1でしたが、システムを拡張できるのはUSBバスのみでした。 制作中に苦情はまったくありませんでした-誰もが非常に満足していました。



このデバイスは非常に成功したため、このビジネスを「個人」の利益のために使用したい、つまりこのデバイスを監視システムに導入したいという要望がありました。 しかし、主なニュアンスであるメッセージキューの欠如を取り除く必要がありました。 私は有名なベンダーから実装原則を取りました(彼はハードウェアとソフトウェアの複合体を提供し、その一部は通知を処理してgsmデバイスに送信するためにsmtpサーバーを上げました)。 このようなスキームは、あらゆる監視システムに組み込まれています。



したがって、必要な知識は長い間得られており、実装に進みます。



SMTPデーモン
 #!/usr/bin/env python2.7 # -*- coding: utf-8 -*- import smtpd import asyncore import email import MySQLdb import subprocess def InsertNewMessage(phone, msg): conn = MySQLdb.connect(host="localhost", # your host, usually localhost user="sms", # your username passwd="sms", # your password db="sms") # name of the data base c = conn.cursor() c.execute('insert into message_queue (phone, message) values ("%s", "%s")' % (phone, msg)) conn.commit() conn.close() class CustomSMTPServer(smtpd.SMTPServer): def process_message(self, peer, mailfrom, rcpttos, data): msg = email.message_from_string(data) phone = rcpttos[0].split('@',1)[0] addr = mailfrom for part in msg.walk(): if part.get_content_type() == "text/plain": # ignore attachments/html body = part.get_payload(decode=True) InsertNewMessage(phone, str(body)) subprocess.Popen("/home/pi/daemons/sms/pygsmd.py", shell=True) server = CustomSMTPServer(('0.0.0.0', 25), None) asyncore.loop()
      
      









先に書いたように、「start-stop-daemon」を使用してデーモン化が発生し、smtpスクリプト自体がサブプロセスを起動してメッセージベースを操作します。



gsmスクリプト
 #!/usr/bin/env python2.7 # -*- coding: utf-8 -*- import serial import time import MySQLdb import commands def gsm_send(port, phone, msg): print 'Sending message: %s to: %s' % (msg, phone) gsm = serial.Serial('/dev/tty%s' % port, 460800, timeout=5, xonxoff = False, rtscts = False, bytesize = serial.EIGHTBITS, parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE ) gsm.write('ATZ\r\n') time.sleep(0.05) gsm.write('AT+CMGF=1\r\n') time.sleep(0.05) gsm.write('''AT+CMGS="''' + phone + '''"\r''') time.sleep(0.05) gsm.write(msg + '\r\n') time.sleep(0.05) gsm.write(chr(26)) time.sleep(0.05) abort_after = 15 start = time.time() output = "" while True: output = output + gsm.readline() #print output if '+CMGS:' in output: #print output gsm.close() return 0 if 'ERROR' in output: #print output gsm.close() return 1 delta = time.time() - start if delta >= abort_after: gsm.close() return 1 def msg_delete(list): conn = MySQLdb.connect(host="localhost", user="sms", passwd="sms", db="sms") c = conn.cursor() c.execute("delete from message_queue where id in %s;" % list) conn.commit() conn.close() def msg_hadle(): list = tuple() conn = MySQLdb.connect(host="localhost", user="sms", passwd="sms", db="sms") c = conn.cursor() c.execute("select * from message_queue") numrows = int(c.rowcount) if numrows > 0: for row in c.fetchall(): result = gsm_send('USB0', ('+' + row[1]), row[2]) if result == 0: list +=(str(row[0]),) conn.close() if len(list) == 1: qlist = str(list).replace(',','') if len(list) > 1: qlist = str(list) if len(list) > 0: msg_delete(qlist) del list while True: try: msg_hadle() except: print "mysql error" time.sleep(10)
      
      









私の監視システムと連動して、デバイスは適切に動作しますが、それほど前には機能していませんでした。 この資料が誰かに役立つことを願っています。



All Articles