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; }
char net_msgp_tpms(char stat) { char k, *s; long p; #if 0 if ((car_tpms_t[0] == 0) && (car_tpms_t[1] == 0) && (car_tpms_t[2] == 0) && (car_tpms_t[3] == 0)) return stat; // No TPMS, no report // ...new stat fn: No TMPS = one report with stale=-1 #endif s = stp_rom(net_scratchpad, "MP-0 W"); for (k = 0; k < 4; k++) { if (car_tpms_t[k] > 0) { p = (long) ((float) car_tpms_p[k] / 0.2755); s = stp_l2f(s, NULL, p, 1); s = stp_i(s, ",", car_tpms_t[k] - 40); s = stp_rom(s, ","); } else { s = stp_rom(s, "0,0,"); } } s = stp_i(s, NULL, car_stale_tpms); return net_msg_encode_statputs(stat, &crc_tpms); }
char net_msgp_capabilities(char stat) { char *s; s = stp_rom(net_scratchpad, "MP-0 V"); if ((can_capabilities != NULL) && (can_capabilities[0] != 0)) { s = stp_rom(s, can_capabilities); s = stp_rom(s, ","); } s = stp_rom(s, "C1-6,C40-41,C49"); return net_msg_encode_statputs(stat, &crc_capabilities); }
BOOL net_sms_handle_temps(char *caller, char *command, char *arguments) { char *s; s = stp_i(net_scratchpad, "Temperatures:\r\n Ambient: ", car_ambient_temp); s = stp_i(s, "C\r\n PEM: ", car_tpem); s = stp_i(s, "C\r\n Motor: ", car_tmotor); s = stp_i(s, "C\r\n Battery: ", car_tbattery); s = stp_rom(s, "C"); if ((car_stale_ambient==0)||(car_stale_temps==0)) s = stp_rom(s, "\r\n (stale)"); net_send_sms_start(caller); net_puts_ram(net_scratchpad); return TRUE; }
void net_send_sms_start(char* number) { if (net_state == NET_STATE_DIAGMODE) { // DIAG mode: screen output net_puts_rom("# "); } else if (net_msg_bufpos) { // NET SMS wrapper mode: nothing to do here // net_put* will write to net_msg_bufpos } else { // MODEM mode: net_puts_rom("AT+CMGS=\""); net_puts_ram(number); net_puts_rom("\"\r\n"); delay100(2); } if ((car_time > 315360000)&& ((sys_features[FEATURE_CARBITS]&FEATURE_CB_SSMSTIME)==0)) { // Car time is valid, and sms time is not disabled char *p = par_get(PARAM_TIMEZONE); char *s = stp_time(net_scratchpad, NULL, car_time + timestring_to_mins(p)*60L); s = stp_rom(s, "\r "); net_puts_ram(net_scratchpad); } }
void net_msg_socalert(void) { char *s; s = stp_i(net_scratchpad, "MP-0 PAALERT!!! CRITICAL SOC LEVEL APPROACHED (", car_SOC); // 95% s = stp_rom(s, "% SOC)"); net_msg_encode_puts(); }
void net_msg_alert(void) { char *s; delay100(2); s = stp_rom(net_scratchpad, "MP-0 PA"); net_prep_stat(s); }
void net_msg_12v_alert(void) { char *s; s = stp_l2f(net_scratchpad, "MP-0 PAALERT!!! 12V BATTERY CRITICAL (", car_12vline, 1); s = stp_l2f(s, "V, ref=", car_12vline_ref, 1); s = stp_rom(s, "V)"); net_msg_encode_puts(); }
BOOL net_sms_handle_diag(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, "DIAG:"); s = stp_i(s, "\n RED Led:", led_code[OVMS_LED_RED]); s = stp_i(s, "\n GRN Led:", led_code[OVMS_LED_GRN]); s = stp_x(s, "\n NET State:0x", net_state); if (car_12vline > 0) { s = stp_l2f(s, "\n 12V Line:", car_12vline, 1); s = stp_l2f(s, " ref=", car_12vline_ref, 1); } #ifndef OVMS_NO_CRASHDEBUG /* DEBUG / QA stats: output crash counter and decode last reason: */ s = stp_i(s, "\n Crashes:", debug_crashcnt); if (debug_crashreason) { s = stp_rom(s, "\n ..last:"); if (debug_crashreason & 0x01) s = stp_rom(s, " BOR"); // Brown Out Reset if (debug_crashreason & 0x02) s = stp_rom(s, " POR"); // Power On Reset if (debug_crashreason & 0x04) s = stp_rom(s, " PD"); // Power-Down Detection if (debug_crashreason & 0x08) s = stp_rom(s, " TO"); // Watchdog Timeout if (debug_crashreason & 0x10) s = stp_rom(s, " RI"); // Reset Instruction if (debug_crashreason & 0x20) s = stp_rom(s, " STKFUL"); // Stack overflow if (debug_crashreason & 0x40) s = stp_rom(s, " STKUNF"); // Stack underflow s = stp_i(s, " - ", debug_checkpoint); } #endif // OVMS_NO_CRASHDEBUG net_puts_ram(net_scratchpad); return TRUE; }
void net_sms_socalert(char* number) { char *s; delay100(10); net_send_sms_start(number); s = stp_i(net_scratchpad, "ALERT!!! CRITICAL SOC LEVEL APPROACHED (", car_SOC); // 95% s = stp_rom(s, "% SOC)"); net_puts_ram(net_scratchpad); net_send_sms_finish(); delay100(5); }
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_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; }
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_vehicletype(s); net_puts_ram(net_scratchpad); return TRUE; }
void net_msg_12v_alert(void) { char *s; delay100(2); net_msg_start(); if (can_minSOCnotified & CAN_MINSOC_ALERT_12V) s = stp_l2f(net_scratchpad, "MP-0 PAALERT!!! 12V BATTERY CRITICAL (", car_12vline, 1); else s = stp_l2f(net_scratchpad, "MP-0 PA12V BATTERY OK (", car_12vline, 1); s = stp_l2f(s, "V, ref=", car_12vline_ref, 1); s = stp_rom(s, "V)"); net_msg_encode_puts(); net_msg_send(); }
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; }
void net_sms_12v_alert(char* number) { char *s; delay100(10); net_send_sms_start(number); if (can_minSOCnotified & CAN_MINSOC_ALERT_12V) s = stp_l2f(net_scratchpad, "MP-0 PAALERT!!! 12V BATTERY CRITICAL (", car_12vline, 1); else s = stp_l2f(net_scratchpad, "MP-0 PA12V BATTERY OK (", car_12vline, 1); s = stp_l2f(s, "V, ref=", car_12vline_ref, 1); s = stp_rom(s, "V)"); net_puts_ram(net_scratchpad); net_send_sms_finish(); delay100(5); }
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; }
void net_send_sms_start(char* number) { if (net_msg_bufpos) { // NET SMS wrapper mode: nothing to do here // net_put* will write to net_msg_bufpos } #ifdef OVMS_DIAGMODULE else if (net_state == NET_STATE_DIAGMODE) { // DIAG mode: screen output net_msg_sendpending = 1; net_puts_rom("# "); } #endif // OVMS_DIAGMODULE else { // MODEM mode: net_puts_rom("AT+CMGS=\""); net_puts_ram(number); net_puts_rom("\"\r\n"); delay100(2); } // ATT: the following code tries to prepend the current time to ALL // outbound SMS. It relies on a) all SMS leaving enough space // to add "HH:MM:SS\r " = 10 chars and b) ALL SMS senders to // call net_send_sms_start() BEFORE preparing the message in // net_scratchpad -- otherwise the prepd message is lost. #ifndef OVMS_NO_SMSTIME if ((car_time > 315360000)&& ((sys_features[FEATURE_CARBITS]&FEATURE_CB_SSMSTIME)==0)) { // Car time is valid, and sms time is not disabled char *p = par_get(PARAM_TIMEZONE); char *s = stp_time(net_scratchpad, NULL, car_time + timestring_to_mins(p)*60L); s = stp_rom(s, "\r "); net_puts_ram(net_scratchpad); } #endif //OVMS_NO_SMSTIME }
BOOL net_sms_handle_version(char *caller, char *command, char *arguments) { unsigned char hwv = 1; char *s; #ifdef OVMS_HW_V2 hwv = 2; #endif 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); net_send_sms_start(caller); net_puts_ram(net_scratchpad); return TRUE; }
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(); }
char *net_prep_stat(char *s) { // convert distance values as needed unsigned int estrange = car_estrange; unsigned int idealrange = car_idealrange; unsigned long odometer = car_odometer; const rom char *unit = " mi"; if (can_mileskm == 'K') { estrange = KmFromMi(estrange); idealrange = KmFromMi(idealrange); odometer = KmFromMi(odometer); unit = " km"; } if (car_time != 0) { char *p = par_get(PARAM_TIMEZONE); s = stp_time(s, NULL, car_time + timestring_to_mins(p)*60L); s = stp_rom(s, "\r "); } if (car_coolingdown>=0) { s = stp_i(s, "Cooldown: ", car_tbattery); s = stp_i(s, "C/",car_cooldown_tbattery); s = stp_i(s, "C (",car_coolingdown); s = stp_i(s, "cycles, ",car_cooldown_timelimit); s = stp_rom(s, "mins remain)"); } if (car_doors1bits.ChargePort) { char fShowVA = TRUE; // Charge port door is open, we are charging switch (car_chargemode) { case 0x00: s = stp_rom(s, "Standard - "); // Charge Mode Standard break; case 0x01: s = stp_rom(s, "Storage - "); // Storage break; case 0x03: s = stp_rom(s, "Range - "); // Range break; case 0x04: s = stp_rom(s, "Performance - "); // Performance } switch (car_chargestate) { case 0x01: s = stp_rom(s, "Charging"); // Charge State Charging break; case 0x02: s = stp_rom(s, "Charging, Topping off"); // Topping off break; case 0x04: s = stp_rom(s, "Charging Done"); // Done fShowVA = FALSE; break; case 0x0d: s = stp_rom(s, "Preparing"); // Preparing break; case 0x0f: s = stp_rom(s, "Charging, Heating"); // Heating break; default: s = stp_rom(s, "Charging Stopped"); // Stopped fShowVA = FALSE; break; } // this causes ACC to think the charge port door has been closed and opened, // which then causes it to do something that makes the coolant pump come on // car_doors1bits.ChargePort = 0; // MJ Close ChargePort, will open next CAN Reading if (fShowVA) { s = stp_i(s, "\r ", car_linevoltage); s = stp_i(s, "V/", car_chargecurrent); s = stp_rom(s, "A"); if (car_chargefull_minsremaining >= 0) { s = stp_i(s,"\r Full: ",car_chargefull_minsremaining); s = stp_rom(s," mins"); } if (car_chargelimit_soclimit > 0) { s = stp_i(s, "\r ", car_chargelimit_soclimit); s = stp_i(s,"%: ",car_chargelimit_minsremaining); s = stp_rom(s," mins"); } if (car_chargelimit_rangelimit > 0) { s = stp_i(s, "\r ", (can_mileskm == 'K')?KmFromMi(car_chargelimit_rangelimit):car_chargelimit_rangelimit); s = stp_rom(s, unit); s = stp_i(s,": ",car_chargelimit_minsremaining); s = stp_rom(s," mins"); } } } else { s = stp_rom(s, "Not charging"); } s = stp_i(s, "\r SOC: ", car_SOC); s = stp_rom(s, "%"); if (idealrange != 0) { s = stp_i(s, "\r Ideal Range: ", idealrange); s = stp_rom(s, unit); } if (estrange != 0) { s = stp_i(s, "\r Est. Range: ", estrange); s = stp_rom(s, unit); } if (odometer != 0) { s = stp_l2f_h(s, "\r ODO: ", odometer, 1); s = stp_rom(s, unit); } if (car_cac100 != 0) { s = stp_l2f_h(s, "\r CAC: ", (unsigned long)car_cac100, 2); } return s; }
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, ",", 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 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_prep_stat(char *s) { if (car_doors1bits.ChargePort) { // Charge port door is open, we are charging switch (car_chargemode) { case 0x00: s = stp_rom(s, "Standard - "); // Charge Mode Standard break; case 0x01: s = stp_rom(s, "Storage - "); // Storage break; case 0x03: s = stp_rom(s, "Range - "); // Range break; case 0x04: s = stp_rom(s, "Performance - "); // Performance } switch (car_chargestate) { case 0x01: s = stp_rom(s, "Charging"); // Charge State Charging break; case 0x02: s = stp_rom(s, "Charging, Topping off"); // Topping off break; case 0x04: s = stp_rom(s, "Charging Done"); // Done break; case 0x0d: s = stp_rom(s, "Preparing"); // Preparing break; case 0x0f: s = stp_rom(s, "Charging, Heating"); // Heating break; default: s = stp_rom(s, "Charging Stopped"); // Stopped } } else { s = stp_rom(s, "Not charging"); } if (can_mileskm == 'M') { s = stp_i(s, "\r Range: ", car_estrange); s = stp_i(s, " - ", car_idealrange); s = stp_rom(s, " mi"); } else { s = stp_i(s, "\r Range: ", MI2KM(car_estrange)); s = stp_i(s, " - ", MI2KM(car_idealrange)); s = stp_rom(s, " km"); } s = stp_i(s, "\r SOC: ", car_SOC); s = stp_rom(s, "%"); if (can_mileskm == 'M') { s = stp_ul(s, "\r ODO: ", car_odometer / 10); s = stp_rom(s, " mi"); } else { s = stp_ul(s, "\r ODO: ", MI2KM(car_odometer / 10)); s = stp_rom(s, " km"); } return s; }
char *net_prep_ctp(char *s, char *argument) { int imStart = car_idealrange; int imTarget = 0; int pctTarget = 0; int cac100 = car_cac100; int volts = car_linevoltage; int amps = car_chargelimit; int degAmbient = car_ambient_temp; int chargemode = car_chargemode; int watts = 0; int imExpect; int minRemain; if (vehicle_fn_minutestocharge == NULL) { return stp_rom(s, "CTP not available"); } // CTP 90s 150e 70% 16800w 160a 24d [S|R|P] while (argument != NULL) { int cch = strlen(argument); strupr(argument); // Convert argument to upper case if (cch > 0) { int val; char chType = argument[cch-1]; argument[cch-1] = 0; if (cch > 1) { val = atoi(argument); switch (chType) { case 'S': imStart = val; break; case 'E': imTarget = val; break; case '%': pctTarget = val; break; case 'W': watts = val; break; case 'V': volts = val; break; case 'A': amps = val; break; case 'C': cac100 = val*100; break; case 'D': degAmbient = val; break; } } else { switch (chType) { case 'S': chargemode = 0; break; case 'R': chargemode = 3; break; case 'P': chargemode = 4; break; } } argument[cch-1] = chType; } argument = net_sms_nextarg(argument); } if (volts > 0 && amps > 0) watts = volts * amps; if (watts < 1000) { s = stp_rom(s, "no power level specified"); return s; } minRemain = vehicle_fn_minutestocharge(chargemode, watts, imStart, imTarget, pctTarget, cac100, degAmbient, &imExpect); s = stp_i(s, NULL, imStart); s = stp_i(s, " to ", imExpect); s = stp_rom(s, " ideal mi\r"); if (minRemain >= 0) { s = stp_i(s, NULL, minRemain/60); s = stp_ulp(s, ":", minRemain % 60, 2, '0'); } else if (minRemain == -3) { s = stp_rom(s, "target reached"); } else { s = stp_i(s, "error: ", minRemain); } return s; }