struct simple_at_commands { char cmd; atcmd_simple *action; }; struct at_commands { const char *cmd; atcmd_query *query; atcmd_set *set; atcmd_help *help; }; struct simple_at_commands simple_at_commands[]= { 0, atcmd_ready, 'h', atcmd_hangup, 'd', atcmd_dial, 'a', atcmd_answer, // 'e', atcmd_echomode, // 'q', atcmd_resultmode, // 's', atcmd_sregister, // 'v', atcmd_verbosemode, // 'x', atcmd_connectmsg, 0, 0, }; struct simple_at_commands amp_at_commands[]= { // 'c', atcmd_setdcdmode, // 'd', atcmd_setdtrmode, 0, 0, }; struct at_commands gsmat[] { // "%ALS", handle_pct_ALS, // "%CGAATT", handle_pct_CGAATT, // "%CGPPP", handle_pct_CGPPP, // "%CME155", handle_pct_CME155, // "%COPSLAC", handle_pct_COPSLAC, // "%CPI", handle_pct_CPI, // "%CPRIM", handle_pct_CPRIM, // "%CREG", handle_pct_CREG, // "%CSQ", handle_pct_CSQ, // "%CSTAT", handle_pct_CSTAT, // "%CTZV", handle_pct_CTZV, // "%DATA", handle_pct_DATA, // "%SATC", handle_pct_SATC, // "%SATR", handle_pct_SATR, "+CBST", handle_plus_CBST, // "+CCFC", handle_plus_CCFC, // "+CCWA", handle_plus_CCWA, // "+CFUN", handle_plus_CFUN, // ? -> +CFUN: 1, = : sets on/off -> 0 // "+CGACT", handle_plus_CGACT, // "+CGEREP", handle_plus_CGEREP, // "+CGMI", handle_plus_CGMI, // "+CGMM", handle_plus_CGMM, // "+CGMR", handle_plus_CGMR, // "+CGREG", handle_plus_CGREG, // "+CGSN", handle_plus_CGSN, // "+CIMI", handle_plus_CIMI, // response: // "+CLCC", handle_plus_CLCC, // response: +CLCC: ... // "+CLIP", handle_plus_CLIP, // "+CLIR", handle_plus_CLIR, // "+CLVL", handle_plus_CLVL, // "+CMEE", handle_plus_CMEE, // "+CMGF", handle_plus_CMGF, // "+CMOD", handle_plus_CMOD, // "+CMUT", handle_plus_CMUT, // ? -> CMUT: 0 // "+CNMI", handle_plus_CNMI, // "+CNUM", handle_plus_CNUM, // "+COLP", handle_plus_COLP, // "+COPS", handle_plus_COPS, // = -> +COPS: ... // "+CPAS", handle_plus_CPAS, // ? -> +CPAS: ... // "+CPBR", handle_plus_CPBR, // =? -> CME ERROR: 100, = -> 0 // "+CPBS", handle_plus_CPBS, // ? -> +CPBS: "MT",0,0 // "+CPIN", handle_plus_CPIN, // ? -> +CPIN: READY // "+CR", handle_plus_CR, // "+CRC", handle_plus_CRC, // "+CREG", handle_plus_CREG, // "+CRSM", handle_plus_CRSM, // = -> +CRSM: .... // "+CSAS", handle_plus_CSAS, // "+CSCB", handle_plus_CSCB, // "+CSCS", handle_plus_CSCS, // "+CSQ", handle_plus_CSQ, // "+CSSN", handle_plus_CSSN, // "+CUSD", handle_plus_CUSD, // "+USSDNF", handle_plus_USSDNF, 0, 0, } struct async_response response[]= { "%CSQ", event_pct_csq, "%CSTAT", event_pct_cstat, "%CREG", event_pct_creg, "%CTZV", event_pct_ctzv, // network time ? "+CGEV", event_plus_cgev, "+CREG", event_plus_creg, "+CGREG", event_plus_cgreg, "+CR", event_plus_cr, // data connect "+CRING", event_plus_cring, "+CLIP", event_plus_clip, }; // grammar: // line: "AT" commandlist? // commandlist: // simplecmd commandlist? // | gsmcmd ( ";" commandlist )? // simplecmd: // "S" \d+ "?" // | "S" \d+ "=" \d+ // | "D" [0-9+W-]+ // | "H" // | "A" // | "BCEFGI-RT-Z" \d* // | "&[A-Z]" \d* // gsmcmd: gsmquery | gsminfo | gsmset | gsmbase // // gsmquery: /[+%]\w+/ "?" // gsminfo: /[+%]\w+/ "=?" // gsmset: /[+%]\w+/ "=" paramlist // gsmbase: /[+%]\w+/ // // paramlist: param ( "," paramlist )? // param: /[0-9a-zA-Z_]+/ // | "\"" [^"]+ "\"" class hayes : public process { public: hayes(queue& in, queue& out) : _in(in), _out(out) { start(); } virtual ~hayes() { stop(); } virtual const char*name() { return "hayes"; } virtual void service() { _in.read(&c, 1); switch(_state) { case 0: if (c=='A' || c=='a') _state++; else _state=0; break; case 1: if (c=='T' || c=='t') _state++; else _state=0; break; case 2: if (c==0x0d) { process_cmd(_cmd); } else _cmd+=c; break; } } void process_cmd(const std::string& cmd) { // todo: split concatenated commands // ATH0+CPAS;+XYZ="abc;qweqew";D123123 if (cmd.size()==0) { response_ok(); } else if (cmd[0]=='+' || cmd[0]=='%') handle_gsmcmd(cmd); else if (cmd[0]=='&') handle_ampcmd(cmd); else if (isalpha(cmd[0])) handle_simplecmd(cmd); } void handle_ampcmd(const std::string& cmd) { } void handle_simplecmd(const std::string& cmd) { } enum { CMD_BASIC, // AT+XYZ CMD_QUERY, // AT+XYZ? CMD_INFO, // AT+XYZ=? CMD_SET // AT+XYZ= }; void handle_gsmcmd(const std::string& cmd) { std::string name; int type; std::string params; split_command(cmd, name, type, params); if (type==CMD_SET) { _set[name].push_back(setitem_t(GetTickCount(),params)); } for (unsigned i=0 ; gsmat[i].cmd ; i++) { if (name==gsmat[i].cmd) { } } } bool split_command(const std::string& cmd, std::string& name, int& type, std::string& params) { size_t itype= cmd.find_first_of("=?", 1); name= cmd.substr(0, itype); if (itype==cmd.npos) { type= CMD_BASIC; return true; } else if (cmd[itype]=='?') { if (cmd.size()!=itype+1) return false; type= CMD_QUERY; return true; } else if (cmd[itype]=='=') { if (cmd.size()==itype+1) return false; if (cmd[itype+1]=='?') { if (cmd.size()!=itype+2) return false; type= CMD_INFO; return true; } type= CMD_SET; params= cmd.substr(itype+1); return true; } else { return false; } } private: int _state; struct setitem_t { uint32_t timestamp; std::string data; }; typedef std::vector setitem_list; typedef std::map sethistory; sethistory _set; };