BOOL net_sms_handle_gprsq(char *caller, char *command, char *arguments) { char *s; if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); s = stp_rom(net_scratchpad, "GPRS:"); s = stp_s(s, "\r\n APN:", par_get(PARAM_GPRSAPN)); s = stp_s(s, "\r\n User:"******"\r\n Password:"******"\r\n GSM:", car_gsmcops); if (!inputs_gsmgprs()) s = stp_rom(s, "\r\n GPRS: DISABLED"); else if (net_msg_serverok) s = stp_rom(s, "\r\n GPRS: OK\r\n Server: Connected OK"); else if (net_state == NET_STATE_READY) s = stp_rom(s, "\r\n GSM: OK\r\n Server: Not connected"); else { s = stp_x(s, "\r\n GSM/GPRS: Not connected (0x", net_state); s = stp_rom(s, ")"); } net_puts_ram(net_scratchpad); return TRUE; }
BOOL net_sms_handle_paramsq(char *caller, char *command, char *arguments) { unsigned char k, splen, msglen; char *p, *s; if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); net_puts_rom("Params:"); msglen=7; for (k=0; k<PARAM_MAX; k++) { p = par_get(k); if (*p != 0) { s = stp_i(net_scratchpad, "\n", k); s = stp_s(s, ":", p); splen = s - net_scratchpad; if((msglen+splen) > 160) { // SMS becomes too long, finish & start next: net_send_sms_finish(); delay100(20); net_send_sms_start(caller); net_puts_rom("Params:"); msglen=7+splen; } net_puts_ram(net_scratchpad); } } return TRUE; }
BOOL net_sms_handle_gsmlockq(char *caller, char *command, char *arguments) { char *p; if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); net_puts_rom("GSMLOCK: "); p = par_get(PARAM_GSMLOCK); if (*p == 0) { net_puts_rom("(none)\r\n"); } else { net_puts_ram(p); net_puts_rom("\r\n"); } stp_s(net_scratchpad, "Current: ", car_gsmcops); net_puts_ram(net_scratchpad); return TRUE; }
BOOL net_sms_handle_serverq(char *caller, char *command, char *arguments) { char *s; if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); s = stp_rom(net_scratchpad, "Server:"); s = stp_s(s, "\r\n IP:", par_get(PARAM_SERVERIP)); s = stp_s(s, "\r\n Password:"******"\r\n Paranoid:", par_get(PARAM_PARANOID)); net_puts_ram(net_scratchpad); return TRUE; }
BOOL net_sms_handle_moduleq(char *caller, char *command, char *arguments) { char *s; if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); s = stp_rom(net_scratchpad, "Module:"); s = stp_s(s, "\r\n VehicleID:", par_get(PARAM_VEHICLEID)); s = stp_s(s, "\r\n Units:", par_get(PARAM_MILESKM)); s = stp_s(s, "\r\n Notifications:", par_get(PARAM_NOTIFIES)); s = stp_s(s, "\r\n VehicleType:", par_get(PARAM_VEHICLETYPE)); net_puts_ram(net_scratchpad); return TRUE; }
BOOL net_sms_handle_passq(char *caller, char *command, char *arguments) { char *p = par_get(PARAM_MODULEPASS); if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); stp_s(net_scratchpad, "Module password: ", p); net_puts_ram(net_scratchpad); return TRUE; }
BOOL net_sms_handle_registerq(char *caller, char *command, char *arguments) { char *p = par_get(PARAM_REGPHONE); if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); stp_s(net_scratchpad, "Registered number: ", p); net_puts_ram(net_scratchpad); return TRUE; }
void net_msg_erroralert(unsigned int errorcode, unsigned long errordata) { char *s; delay100(2); net_msg_start(); s = stp_s(net_scratchpad, "MP-0 PE", car_type); s = stp_ul(s, ",", (unsigned long)errorcode); s = stp_ul(s, ",", (unsigned long)errordata); net_msg_encode_puts(); net_msg_send(); }
char net_msgp_firmware(char stat) { // Send firmware version and GSM signal level char *s; unsigned char hwv = 1; #ifdef OVMS_HW_V2 hwv = 2; #endif s = stp_i(net_scratchpad, "MP-0 F", ovms_firmware[0]); s = stp_i(s, ".", ovms_firmware[1]); s = stp_i(s, ".", ovms_firmware[2]); s = stp_s(s, "/", par_get(PARAM_VEHICLETYPE)); s = stp_i(s, "/V", hwv); s = stp_s(s, ",", car_vin); s = stp_i(s, ",", net_sq); s = stp_i(s, ",", sys_features[FEATURE_CANWRITE]); s = stp_s(s, ",", car_type); s = stp_s(s, ",", car_gsmcops); return net_msg_encode_statputs(stat, &crc_firmware); }
void net_msg_reply_ussd(char *buf, unsigned char buflen) { // called from net_state_activity() // buf contains a "+CUSD:" USSD command result // parse and return as command reply: char *s, *t = NULL; // Server not ready? abort // TODO: store, resend when server is connected if ((!net_msg_serverok) || (!buf) || (!buflen)) return; // isolate USSD reply text if (t = memchr((void *) buf, '"', buflen)) { ++t; buflen -= (t - buf); buf = t; // start of USSD string while ((*t) && (*t != '"') && ((t - buf) < buflen)) { if (*t == ',') // "escape" comma for MP-0 *t = '.'; t++; } *t = 0; // end of USSD string } // format reply: s = stp_i(net_scratchpad, "MP-0 c", CMD_SendUSSD); if (t) s = stp_s(s, ",0,", buf); else s = stp_rom(s, ",1,Invalid USSD result"); // send reply: if (net_msg_sendpending > 0) { delay100(20); // HACK... should buffer & retry later... but RAM is precious s = NULL; // flag } net_msg_start(); net_msg_encode_puts(); net_msg_send(); if (!s) delay100(20); // HACK: give modem additional time if there was sendpending>0 }
BOOL net_sms_handle_version(char *caller, char *command, char *arguments) { unsigned char hwv = 1; char *s; #ifdef OVMS_HW_V2 hwv = 2; #endif net_send_sms_start(caller); s = stp_i(net_scratchpad, "OVMS Firmware version: ", ovms_firmware[0]); s = stp_i(s, ".", ovms_firmware[1]); s = stp_i(s, ".", ovms_firmware[2]); s = stp_s(s, "/", par_get(PARAM_VEHICLETYPE)); if (vehicle_version) s = stp_rom(s, vehicle_version); s = stp_i(s, "/V", hwv); s = stp_rs(s, "/", OVMS_BUILDCONFIG); s = stp_s(s, "\r\n CarType:", car_type); s = stp_s(s, "\r\n VIN:", car_vin); net_puts_ram(net_scratchpad); return TRUE; }
BOOL net_sms_handle_vehicleq(char *caller, char *command, char *arguments) { char *s; if (sys_features[FEATURE_CARBITS]&FEATURE_CB_SOUT_SMS) return FALSE; net_send_sms_start(caller); s = stp_rom(net_scratchpad, "Vehicle:"); s = stp_s(s, "\r\n VehicleType: ", par_get(PARAM_VEHICLETYPE)); net_puts_ram(net_scratchpad); return TRUE; }
char net_msgp_group(char stat, char groupnumber, char *groupname) { char *s; s = stp_s(net_scratchpad, "MP-0 g", groupname); s = stp_i(s, ",", car_SOC); s = stp_i(s, ",", car_speed); s = stp_i(s, ",", car_direction); s = stp_i(s, ",", car_altitude); s = stp_i(s, ",", car_gpslock); s = stp_i(s, ",", car_stale_gps); s = stp_latlon(s, ",", car_latitude); s = stp_latlon(s, ",", car_longitude); if (groupnumber == 1) return net_msg_encode_statputs(stat, &crc_group1); else return net_msg_encode_statputs(stat, &crc_group2); }
void net_msg_reply_ussd(char *buf) { // called from net_state_activity() // buf contains a "+CUSD:" USSD command result // parse and return as command reply: char *s, *t = NULL; // Server not ready? abort // TODO: store, resend when server is connected if ((!net_msg_serverok) || (!buf)) return; // isolate USSD reply text if (t = strchr(buf, '"')) { buf = ++t; // start of USSD string while ((*t) && (*t != '"')) { if (*t == ',') // replace comma *t = '.'; t++; } *t = 0; // end of USSD string } // format reply: s = stp_i(net_scratchpad, "MP-0 c", CMD_SendUSSD); if (t) s = stp_s(s, ",0,", buf); else s = stp_rom(s, ",1,Invalid USSD result"); // send reply: if (net_msg_sendpending > 0) delay100(20); // HACK... should abort, buffer & retry later... net_msg_start(); net_msg_encode_puts(); net_msg_send(); }
BOOL net_msg_cmd_exec(void) { int k; char *p, *s; delay100(2); CHECKPOINT(0x43) switch (net_msg_cmd_code) { case 1: // Request feature list (params unused) for (k=0;k<FEATURES_MAX;k++) { s = stp_i(net_scratchpad, "MP-0 c1,0,", k); s = stp_i(s, ",", FEATURES_MAX); s = stp_i(s, ",", sys_features[k]); net_msg_encode_puts(); } break; case 2: // Set feature (params: feature number, value) for (p=net_msg_cmd_msg;(*p != 0)&&(*p != ',');p++) ; // check if a value exists and is separated by a comma if (*p == ',') { *p++ = 0; // At this point, <net_msg_cmd_msg> points to the command, and <p> to the param value k = atoi(net_msg_cmd_msg); if ((k>=0)&&(k<FEATURES_MAX)) { sys_features[k] = atoi(p); if (k>=FEATURES_MAP_PARAM) // Top N features are persistent par_set(PARAM_FEATURE_S+(k-FEATURES_MAP_PARAM), p); if (k == FEATURE_CANWRITE) vehicle_initialise(); STP_OK(net_scratchpad, net_msg_cmd_code); } else { STP_INVALIDRANGE(net_scratchpad, net_msg_cmd_code); } } else { STP_INVALIDSYNTAX(net_scratchpad, net_msg_cmd_code); } net_msg_encode_puts(); break; case 3: // Request parameter list (params unused) for (k=0;k<PARAM_MAX;k++) { p = par_get(k); if (k==PARAM_SERVERPASS) *p=0; // Don't show netpass1 s = stp_i(net_scratchpad, "MP-0 c3,0,", k); s = stp_i(s, ",", PARAM_MAX); s = stp_s(s, ",", p); net_msg_encode_puts(); } break; case 4: // Set parameter (params: param number, value) for (p=net_msg_cmd_msg;(*p != 0)&&(*p != ',');p++) ; // check if a value exists and is separated by a comma if (*p == ',') { *p++ = 0; // At this point, <net_msg_cmd_msg> points to the command, and <p> to the param value k = atoi(net_msg_cmd_msg); if ((k>=0)&&(k<PARAM_FEATURE_S)) { par_set(k, p); STP_OK(net_scratchpad, net_msg_cmd_code); if ((k==PARAM_MILESKM) || (k==PARAM_VEHICLETYPE)) vehicle_initialise(); #ifdef OVMS_ACCMODULE // Reset the ACC state it an ACC parameter is changed if ((k>=PARAM_ACC_S)&&(k<(PARAM_ACC_S+PARAM_ACC_COUNT))) acc_state_enter(ACC_STATE_FIRSTRUN); #endif } else { STP_INVALIDRANGE(net_scratchpad, net_msg_cmd_code); } } else { STP_INVALIDSYNTAX(net_scratchpad, net_msg_cmd_code); } net_msg_encode_puts(); break; case 5: // Reboot (params unused) STP_OK(net_scratchpad, net_msg_cmd_code); net_msg_encode_puts(); net_state_enter(NET_STATE_HARDSTOP); break; case 6: // CHARGE ALERT (params unused) net_msg_alert(); net_msg_encode_puts(); break; case 7: // SMS command wrapper // process command: net_msg_bufpos = net_msg_scratchpad; k = net_sms_in(par_get(PARAM_REGPHONE), net_msg_cmd_msg); net_msg_bufpos = NULL; // output is now in net_msg_scratchpad // create return string: s = stp_i(net_scratchpad, NET_MSG_CMDRESP, net_msg_cmd_code); s = stp_i(s, ",", 1-k); // 0=ok 1=error if (k) { *s++ = ','; for (p = net_msg_scratchpad; *p; p++) { if (*p == '\n') *s++ = '\r'; // translate LF to CR else if (*p == ',') *s++ = ';'; // translate , to ; else *s++ = *p; } *s = 0; } // send return string: net_msg_encode_puts(); break; case 40: // Send SMS (params: phone number, SMS message) for (p=net_msg_cmd_msg;(*p != 0)&&(*p != ',');p++) ; // check if a value exists and is separated by a comma if (*p == ',') { *p++ = 0; // At this point, <net_msg_cmd_msg> points to the phone number, and <p> to the SMS message net_send_sms_start(net_msg_cmd_msg); net_puts_ram(p); net_puts_rom("\x1a"); delay100(5); net_msg_start(); STP_OK(net_scratchpad, net_msg_cmd_code); } else { net_msg_start(); STP_INVALIDSYNTAX(net_scratchpad, net_msg_cmd_code); } net_msg_encode_puts(); delay100(2); break; case 41: // Send MMI/USSD Codes (param: USSD_CODE) net_puts_rom("AT+CUSD=1,\""); net_puts_ram(net_msg_cmd_msg); net_puts_rom("\",15\r"); // cmd reply #1 to acknowledge command: delay100(5); net_msg_start(); STP_OK(net_scratchpad, net_msg_cmd_code); net_msg_encode_puts(); delay100(2); // cmd reply #2 sent on USSD response, see net_msg_reply_ussd() break; case 49: // Send raw AT command (param: raw AT command) net_puts_ram(net_msg_cmd_msg); net_puts_rom("\r"); delay100(5); net_msg_start(); STP_OK(net_scratchpad, net_msg_cmd_code); net_msg_encode_puts(); delay100(2); break; default: return FALSE; } return TRUE; }
BOOL net_msg_cmd_exec(void) { int k; char *p, *s; delay100(2); CHECKPOINT(0x43) switch (net_msg_cmd_code) { case 1: // Request feature list (params unused) for (k=0;k<FEATURES_MAX;k++) { s = stp_i(net_scratchpad, "MP-0 c1,0,", k); s = stp_i(s, ",", FEATURES_MAX); s = stp_i(s, ",", sys_features[k]); net_msg_encode_puts(); } break; case 2: // Set feature (params: feature number, value) for (p=net_msg_cmd_msg;(*p != 0)&&(*p != ',');p++) ; // check if a value exists and is separated by a comma if (*p == ',') { *p++ = 0; // At this point, <net_msg_cmd_msg> points to the command, and <p> to the param value k = atoi(net_msg_cmd_msg); if ((k>=0)&&(k<FEATURES_MAX)) { sys_features[k] = atoi(p); if (k>=FEATURES_MAP_PARAM) // Top N features are persistent par_set(PARAM_FEATURE_S+(k-FEATURES_MAP_PARAM), p); if (k == FEATURE_CANWRITE) vehicle_initialise(); STP_OK(net_scratchpad, net_msg_cmd_code); } else { STP_INVALIDRANGE(net_scratchpad, net_msg_cmd_code); } } else { STP_INVALIDSYNTAX(net_scratchpad, net_msg_cmd_code); } net_msg_encode_puts(); break; case 3: // Request parameter list (params unused) for (k=0;k<PARAM_MAX;k++) { p = par_get(k); if (k==PARAM_SERVERPASS) *p=0; // Don't show netpass1 s = stp_i(net_scratchpad, "MP-0 c3,0,", k); s = stp_i(s, ",", PARAM_MAX); s = stp_s(s, ",", p); net_msg_encode_puts(); } break; case 4: // Set parameter (params: param number, value) for (p=net_msg_cmd_msg;(*p != 0)&&(*p != ',');p++) ; // check if a value exists and is separated by a comma if (*p == ',') { *p++ = 0; // At this point, <net_msg_cmd_msg> points to the command, and <p> to the param value k = atoi(net_msg_cmd_msg); if ((k>=0)&&(k<PARAM_FEATURE_S)) { par_set(k, p); STP_OK(net_scratchpad, net_msg_cmd_code); if ((k==PARAM_MILESKM) || (k==PARAM_VEHICLETYPE)) vehicle_initialise(); } else { STP_INVALIDRANGE(net_scratchpad, net_msg_cmd_code); } } else { STP_INVALIDSYNTAX(net_scratchpad, net_msg_cmd_code); } net_msg_encode_puts(); break; case 5: // Reboot (params unused) STP_OK(net_scratchpad, net_msg_cmd_code); net_msg_encode_puts(); net_state_enter(NET_STATE_HARDSTOP); break; case 6: // CHARGE ALERT (params unused) net_msg_alert(); net_msg_encode_puts(); break; case 40: // Send SMS (params: phone number, SMS message) for (p=net_msg_cmd_msg;(*p != 0)&&(*p != ',');p++) ; // check if a value exists and is separated by a comma if (*p == ',') { *p++ = 0; // At this point, <net_msg_cmd_msg> points to the phone number, and <p> to the SMS message net_send_sms_start(net_msg_cmd_msg); net_puts_ram(p); net_puts_rom("\x1a"); delay100(5); net_msg_start(); STP_OK(net_scratchpad, net_msg_cmd_code); } else { net_msg_start(); STP_INVALIDSYNTAX(net_scratchpad, net_msg_cmd_code); } net_msg_encode_puts(); delay100(2); break; case 41: // Send MMI/USSD Codes (param: USSD_CODE) net_puts_rom("AT+CUSD=1,\""); net_puts_ram(net_msg_cmd_msg); net_puts_rom("\",15\r"); // cmd reply #1 to acknowledge command: delay100(5); net_msg_start(); STP_OK(net_scratchpad, net_msg_cmd_code); net_msg_encode_puts(); delay100(2); // cmd reply #2 sent on USSD response, see net_msg_reply_ussd() break; case 49: // Send raw AT command (param: raw AT command) net_puts_ram(net_msg_cmd_msg); net_puts_rom("\r"); delay100(5); net_msg_start(); STP_OK(net_scratchpad, net_msg_cmd_code); net_msg_encode_puts(); delay100(2); break; default: return FALSE; } return TRUE; }
void net_msg_server_welcome(char *msg) { // The server has sent a welcome (token <space> base64digest) char *d,*p,*s; int k; unsigned char hwv = 1; #ifdef OVMS_HW_V2 hwv = 2; #endif if( !msg ) return; for (d=msg;(*d != 0)&&(*d != ' ');d++) ; if (*d != ' ') return; *d++ = 0; // At this point, <msg> is token, and <x> is base64digest // (both null-terminated) // Check for token-replay attack if (strcmp(token,msg)==0) return; // Server is using our token! // Validate server token p = par_get(PARAM_SERVERPASS); hmac_md5(msg, strlen(msg), p, strlen(p), digest); base64encode(digest, MD5_SIZE, net_scratchpad); if (strcmp(d,net_scratchpad)!=0) return; // Invalid server digest // Ok, at this point, our token is ok strcpy(net_scratchpad,msg); strcat(net_scratchpad,token); hmac_md5(net_scratchpad,strlen(net_scratchpad),p,strlen(p),digest); // Setup, and prime the rx and tx cryptos RC4_setup(&rx_crypto1, &rx_crypto2, digest, MD5_SIZE); for (k=0;k<1024;k++) { net_scratchpad[0] = 0; RC4_crypt(&rx_crypto1, &rx_crypto2, net_scratchpad, 1); } RC4_setup(&tx_crypto1, &tx_crypto2, digest, MD5_SIZE); for (k=0;k<1024;k++) { net_scratchpad[0] = 0; RC4_crypt(&tx_crypto1, &tx_crypto2, net_scratchpad, 1); } net_msg_serverok = 1; p = par_get(PARAM_PARANOID); if (*p == 'P') { // Paranoid mode initialisation if (ptokenmade==0) { // We need to make the ptoken for (k=0;k<TOKEN_SIZE;k++) { ptoken[k] = cb64[rand()%64]; } ptoken[TOKEN_SIZE] = 0; } // To be truly paranoid, we must send the paranoid token to the server ;-) ptokenmade=0; // Leave it off for the MP-0 ET message strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 ET"); strcat(net_scratchpad,ptoken); net_msg_start(); net_msg_encode_puts(); net_msg_send(); ptokenmade=1; // And enable paranoid mode from now on... // And calculate the pdigest for future use p = par_get(PARAM_MODULEPASS); hmac_md5(ptoken, strlen(ptoken), p, strlen(p), pdigest); } else { ptokenmade = 0; // This disables paranoid mode } /* DEBUG / QA stats: Send crash counter and last reason: * * MP-0 H*-OVM-DebugCrash,0,2592000 * ,<firmware_version>/<vehicle_type><vehicle_version>/V<hardware_version> * ,<crashcnt>,<crashreason>,<checkpoint> */ if (debug_crashreason & 0x80) { debug_crashreason &= ~0x80; // clear checkpoint hold bit s = stp_i(net_scratchpad, "MP-0 H*-OVM-DebugCrash,0,2592000,", ovms_firmware[0]); s = stp_i(s, ".", ovms_firmware[1]); s = stp_i(s, ".", ovms_firmware[2]); s = stp_s(s, "/", par_get(PARAM_VEHICLETYPE)); if (vehicle_version) s = stp_rom(s, vehicle_version); s = stp_i(s, "/V", hwv); s = stp_i(s, ",", debug_crashcnt); s = stp_x(s, ",", debug_crashreason); s = stp_i(s, ",", debug_checkpoint); delay100(20); net_msg_start(); net_msg_encode_puts(); net_msg_send(); } #ifdef OVMS_LOGGINGMODULE logging_serverconnect(); #endif // #ifdef OVMS_LOGGINGMODULE }
char net_msgp_stat(char stat) { char *p, *s; p = par_get(PARAM_MILESKM); s = stp_i(net_scratchpad, "MP-0 S", car_SOC); s = stp_s(s, ",", p); s = stp_i(s, ",", car_linevoltage); s = stp_i(s, ",", car_chargecurrent); switch (car_chargestate) { case 0x01: s = stp_rom(s, ",charging"); break; case 0x02: s = stp_rom(s, ",topoff"); break; case 0x04: s = stp_rom(s, ",done"); break; case 0x0d: s = stp_rom(s, ",prepare"); break; case 0x0f: s = stp_rom(s, ",heating"); break; default: s = stp_rom(s, ",stopped"); } switch (car_chargemode) { case 0x00: s = stp_rom(s, ",standard"); break; case 0x01: s = stp_rom(s, ",storage"); break; case 0x03: s = stp_rom(s, ",range"); break; case 0x04: s = stp_rom(s, ",performance"); break; default: s = stp_rom(s, ","); } if (*p == 'M') // Kmh or Miles { s = stp_i(s, ",", car_idealrange); s = stp_i(s, ",", car_estrange); } else { s = stp_i(s, ",", KmFromMi(car_idealrange)); s = stp_i(s, ",", KmFromMi(car_estrange)); } s = stp_i(s, ",", car_chargelimit); s = stp_i(s, ",", car_chargeduration); s = stp_i(s, ",", car_charge_b4); s = stp_i(s, ",", car_chargekwh); s = stp_i(s, ",", car_chargesubstate); s = stp_i(s, ",", car_chargestate); s = stp_i(s, ",", car_chargemode); s = stp_i(s, ",", car_timermode); s = stp_i(s, ",", car_timerstart); s = stp_i(s, ",", car_stale_timer); s = stp_l2f(s, ",", (unsigned long)car_cac100, 2); s = stp_i(s, ",", car_chargefull_minsremaining); s = stp_i(s, ",", car_chargelimit_minsremaining); s = stp_i(s, ",", car_chargelimit_rangelimit); s = stp_i(s, ",", car_chargelimit_soclimit); s = stp_i(s, ",", car_coolingdown); s = stp_i(s, ",", car_cooldown_tbattery); s = stp_i(s, ",", car_cooldown_timelimit); s = stp_i(s, ",", car_chargeestimate); return net_msg_encode_statputs(stat, &crc_stat); }
char net_msgp_stat(char stat) { char *p, *s; p = par_get(PARAM_MILESKM); s = stp_i(net_scratchpad, "MP-0 S", car_SOC); s = stp_s(s, ",", p); s = stp_i(s, ",", car_linevoltage); s = stp_i(s, ",", car_chargecurrent); switch (car_chargestate) { case 0x01: s = stp_rom(s, ",charging"); break; case 0x02: s = stp_rom(s, ",topoff"); break; case 0x04: s = stp_rom(s, ",done"); break; case 0x0d: s = stp_rom(s, ",prepare"); break; case 0x0f: s = stp_rom(s, ",heating"); break; default: s = stp_rom(s, ",stopped"); } switch (car_chargemode) { case 0x00: s = stp_rom(s, ",standard"); break; case 0x01: s = stp_rom(s, ",storage"); break; case 0x03: s = stp_rom(s, ",range"); break; case 0x04: s = stp_rom(s, ",performance"); break; default: s = stp_rom(s, ","); } if (*p == 'M') // Kmh or Miles { s = stp_i(s, ",", car_idealrange); s = stp_i(s, ",", car_estrange); } else { s = stp_i(s, ",", MI2KM(car_idealrange)); s = stp_i(s, ",", MI2KM(car_estrange)); } s = stp_i(s, ",", car_chargelimit); s = stp_i(s, ",", car_chargeduration); s = stp_i(s, ",", car_charge_b4); s = stp_i(s, ",", car_chargekwh); s = stp_i(s, ",", car_chargesubstate); s = stp_i(s, ",", car_chargestate); s = stp_i(s, ",", car_chargemode); s = stp_i(s, ",", car_timermode); s = stp_i(s, ",", car_timerstart); s = stp_i(s, ",", car_stale_timer); return net_msg_encode_statputs(stat, &crc_stat); }
char *stp_vehicletype(char *s) { s = stp_s(s, "\r\n VehicleType:", par_get(PARAM_VEHICLETYPE)); s = stp_s(s, "\r\n CarType:", car_type); return s; }