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; }
// Register to the NET OVMS server void net_msg_register(void) { char k; char *p; unsigned int sr; // Make a (semi-)random client token sr = TMR0L*256; sr += TMR0H; for (k=0;k<8;k++) { sr += can_databuffer[k]; } srand(sr); for (k=0;k<TOKEN_SIZE;k++) { token[k] = cb64[rand()%64]; } token[TOKEN_SIZE] = 0; p = par_get(PARAM_SERVERPASS); hmac_md5(token, TOKEN_SIZE, p, strlen(p), digest); net_puts_rom("MP-C 0 "); net_puts_ram(token); net_puts_rom(" "); base64encodesend(digest, MD5_SIZE); net_puts_rom(" "); p = par_get(PARAM_VEHICLEID); net_puts_ram(p); net_puts_rom("\r\n"); }
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); } }
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; }
//////////////////////////////////////////////////////////////////////// // can_initialise() // This function is an entry point from the main() program loop, and // gives the CAN framework an opportunity to initialise itself. // void can_initialise(void) { char *p; car_type[0] = 'V'; // Car is type VA - Volt/Ampera car_type[1] = 'A'; car_type[2] = 0; CANCON = 0b10010000; // Initialize CAN while (!CANSTATbits.OPMODE2); // Wait for Configuration mode // We are now in Configuration Mode RXB0CON = 0b00000000; // RX buffer0 uses Mask RXM0 and filters RXF0, RXF1 RXM0SIDL = 0b10100000; RXM0SIDH = 0b11111111; // Set Mask0 to 0x7fd RXF0SIDL = 0b00000000; // Setup Filter0 and Mask so that only CAN ID 0x100 and 0x102 will be accepted RXF0SIDH = 0b00100000; // Set Filter0 to 0x100 RXB1CON = 0b00000000; // RX buffer1 uses Mask RXM1 and filters RXF2, RXF3, RXF4, RXF5 RXM1SIDL = 0b11100000; RXM1SIDH = 0b11111111; // Set Mask1 to 0x7ff RXF2SIDL = 0b10000000; // Setup Filter2 so that CAN ID 0x344 will be accepted RXF2SIDH = 0b01101000; RXF3SIDL = 0b01000000; // Setup Filter3 so that CAN ID 0x402 will be accepted RXF3SIDH = 0b10000000; RXF4SIDL = 0b00000000; // Setup Filter4 so that CAN ID 0x400 will be accepted RXF4SIDH = 0b10000000; BRGCON1 = 0; // SET BAUDRATE to 1 Mbps BRGCON2 = 0xD2; BRGCON3 = 0x02; CIOCON = 0b00100000; // CANTX pin will drive VDD when recessive if (sys_features[FEATURE_CANWRITE]>0) { CANCON = 0b00000000; // Normal mode } else { CANCON = 0b01100000; // Listen only mode, Receive bufer 0 } RCONbits.IPEN = 1; // Enable Interrupt Priority PIE3bits.RXB1IE = 1; // CAN Receive Buffer 1 Interrupt Enable bit PIE3bits.RXB0IE = 1; // CAN Receive Buffer 0 Interrupt Enable bit IPR3 = 0b00000011; // high priority interrupts for Buffers 0 and 1 p = par_get(PARAM_MILESKM); can_mileskm = *p; can_lastspeedmsg[0] = 0; can_lastspeedrpt = 0; }
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_sms_stat(char* number) { char *p; #ifdef OVMS_SUPPRESS_OUTGOING_SMS return; #endif delay100(2); net_send_sms_start(number); switch (car_chargemode) { case 0x00: net_puts_rom("Standard - "); // Charge Mode Standard break; case 0x01: net_puts_rom("Storage - "); // Storage break; case 0x03: net_puts_rom("Range - "); // Range break; case 0x04: net_puts_rom("Performance - "); // Performance } switch (car_chargestate) { case 0x01: net_puts_rom("Charging"); // Charge State Charging break; case 0x02: net_puts_rom("Charging, Topping off"); // Topping off break; case 0x04: net_puts_rom("Charging Done"); // Done break; default: net_puts_rom("Charging Stopped"); // Stopped } net_puts_rom(" \rIdeal Range: "); // Ideal Range p = par_get(PARAM_MILESKM); if (*p == 'M') // Kmh or Miles sprintf(net_scratchpad, (rom far char*)"%u mi", car_idealrange); // Miles else sprintf(net_scratchpad, (rom far char*)"%u Km", (unsigned int) (((float) car_idealrange * 1.609))+0.5); // Kmh net_puts_ram(net_scratchpad); net_puts_rom(" \rSOC: "); sprintf(net_scratchpad, (rom far char*)"%u%%", car_SOC); // 95% net_puts_ram(net_scratchpad); net_puts_rom("\x1a"); }
// We start with two helper functions unsigned char net_sms_checkcaller(char *caller) { char *p = par_get(PARAM_REGPHONE); if (*p && strncmp(p,caller,strlen(p)) == 0) return 1; else { if ((sys_features[FEATURE_CARBITS]&FEATURE_CB_SAD_SMS) == 0) net_send_sms_rom(caller,NET_MSG_DENIED); return 0; } }
unsigned char net_sms_checkpassarg(char *caller, char *arguments) { char *p = par_get(PARAM_MODULEPASS); if ((arguments != NULL)&&(*p && strncmp(p,arguments,strlen(p))==0)) return 1; else { if ((sys_features[FEATURE_CARBITS]&FEATURE_CB_SAD_SMS) == 0) net_send_sms_rom(caller,NET_MSG_DENIED); return 0; } }
void net_msg_alert(void) { char *p; delay100(2); net_msg_start(); strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 PA"); switch (car_chargemode) { case 0x00: strcatpgm2ram(net_scratchpad,(char const rom far *)"Standard - "); // Charge Mode Standard break; case 0x01: strcatpgm2ram(net_scratchpad,(char const rom far *)"Storage - "); // Storage break; case 0x03: strcatpgm2ram(net_scratchpad,(char const rom far *)"Range - "); // Range break; case 0x04: strcatpgm2ram(net_scratchpad,(char const rom far *)"Performance - "); // Performance } switch (car_chargestate) { case 0x01: strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging"); // Charge State Charging break; case 0x02: strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging, Topping off"); // Topping off break; case 0x04: strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging Done"); // Done break; default: strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging Stopped"); // Stopped } strcatpgm2ram(net_scratchpad,(char const rom far *)"\rIdeal Range: "); // Ideal Range p = par_get(PARAM_MILESKM); if (*p == 'M') // Kmh or Miles sprintf(net_msg_scratchpad, (rom far char*)"%u mi", car_idealrange); // Miles else sprintf(net_msg_scratchpad, (rom far char*)"%u Km", (unsigned int) ((float) car_idealrange * 1.609)); // Kmh strcat((char*)net_scratchpad,net_msg_scratchpad); strcatpgm2ram(net_scratchpad,(char const rom far *)" SOC: "); sprintf(net_msg_scratchpad, (rom far char*)"%u%%", car_SOC); // 95% strcat(net_scratchpad,net_msg_scratchpad); net_msg_encode_puts(); net_msg_send(); }
//////////////////////////////////////////////////////////////////////// // net_notify_status() // Emits a status notification error to the user (by SMS) // upon request (e.g. by an incoming call or sms STAT command). // void net_notify_status(void) { // Emit an unsolicited notification showing current status char *p,*q; p = par_get(PARAM_NOTIFIES); if (strstrrampgm(p,(char const rom far*)"SMS") != NULL) { net_sms_notify = 1; } if (strstrrampgm(p,(char const rom far*)"IP") != NULL) { net_msg_notify = 1; } }
void net_msg_stat(void) { char *p; strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 S"); p = par_get(PARAM_MILESKM); sprintf(net_msg_scratchpad,(rom far char*)"%d,%s,%d,%d,",car_SOC,p,car_linevoltage,car_chargecurrent); strcat(net_scratchpad,net_msg_scratchpad); switch (car_chargestate) { case 0x01: strcatpgm2ram(net_scratchpad,(char const rom far*)"charging,"); // Charge State Charging break; case 0x02: strcatpgm2ram(net_scratchpad,(char const rom far*)"topoff,"); // Topping off break; case 0x04: strcatpgm2ram(net_scratchpad,(char const rom far*)"done,"); // Done break; default: strcatpgm2ram(net_scratchpad,(char const rom far*)"stopped,"); // Stopped } switch (car_chargemode) { case 0x00: strcatpgm2ram(net_scratchpad,(char const rom far*)"standard,"); // Charge Mode Standard break; case 0x01: strcatpgm2ram(net_scratchpad,(char const rom far*)"storage,"); // Storage break; case 0x03: strcatpgm2ram(net_scratchpad,(char const rom far*)"range,"); // Range break; case 0x04: strcatpgm2ram(net_scratchpad,(char const rom far*)"performance,"); // Performance default: strcatpgm2ram(net_scratchpad,(char const rom far*)","); } if (*p == 'M') // Kmh or Miles sprintf(net_msg_scratchpad, (rom far char*)"%u,", car_idealrange); else sprintf(net_msg_scratchpad, (rom far char*)"%u,", (unsigned int) ((float) car_idealrange * 1.609)); strcat(net_scratchpad,net_msg_scratchpad); if (*p == 'M') // Kmh or Miles sprintf(net_msg_scratchpad, (rom far char*)"%u", car_estrange); else sprintf(net_msg_scratchpad, (rom far char*)"%u", (unsigned int) ((float) car_estrange * 1.609)); strcat(net_scratchpad,net_msg_scratchpad); net_msg_encode_puts(); }
void net_sms_params(char* number) { unsigned char k; char *p; net_send_sms_start(number); net_puts_rom("Params:"); for (k=0;k<PARAM_MAX;k++) { sprintf(net_scratchpad, (rom far char*)" %u:", k); net_puts_ram(net_scratchpad); net_puts_ram(par_get(k)); } net_puts_rom("\x1a"); }
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_ap(char *caller, char *command, char *arguments) { unsigned char d = 0; char *p = par_get(PARAM_MODULEPASS); while ((d < PARAM_MAX)&&(arguments != NULL)) { if ((arguments[0]=='-')&&(arguments[1]==0)) par_set(d++, arguments+1); else par_set(d++, arguments); arguments = net_sms_nextarg(arguments); } if (net_state != NET_STATE_DIAGMODE) net_state_enter(NET_STATE_FIRSTRUN); return FALSE; }
void net_sms_params(char* number) { unsigned char k; char *p; #ifdef OVMS_SUPPRESS_OUTGOING_SMS return; #endif net_send_sms_start(number); net_puts_rom("Params:"); for (k=0;k<PARAM_MAX;k++) { sprintf(net_scratchpad, (rom far char*)" %u:", k); net_puts_ram(net_scratchpad); net_puts_ram(par_get(k)); } net_puts_rom("\x1a"); }
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; }
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 main(void) { unsigned char x, y; // DEBUG / QA stats: get last reset reason: x = (~RCON) & 0x1f; if (STKPTRbits.STKFUL) x += 32; if (STKPTRbits.STKUNF) x += 64; // ...clear RCON: RCONbits.NOT_BOR = 1; // b0 = 1 = Brown Out Reset RCONbits.NOT_POR = 1; // b1 = 2 = Power On Reset //RCONbits.NOT_PD = 1; // b2 = 4 = Power Down detection //RCONbits.NOT_TO = 1; // b3 = 8 = watchdog TimeOut occured RCONbits.NOT_RI = 1; // b4 = 16 = Reset Instruction if (x == 3) // 3 = normal Power On { debug_crashreason = 0; debug_crashcnt = 0; #ifdef OVMS_LOGGINGMODULE logging_initialise(); #endif } else { debug_crashreason = x | 0x80; // 0x80 = keep checkpoint until sent to server debug_crashcnt++; } CHECKPOINT(0x20) for (x = 0; x < FEATURES_MAP_PARAM; x++) sys_features[x] = 0; // Turn off the features // The top N features are persistent for (x = FEATURES_MAP_PARAM; x < FEATURES_MAX; x++) { sys_features[x] = atoi(par_get(PARAM_FEATURE_S + (x - FEATURES_MAP_PARAM))); } // Make sure cooldown is off car_coolingdown = -1; // Port configuration inputs_initialise(); TRISB = 0xFE; // Timer 0 enabled, Fosc/4, 16 bit mode, prescaler 1:256 // This gives us one tick every 51.2uS before prescale (13.1ms after) T0CON = 0b10000111; // @ 5Mhz => 51.2uS // Initialisation... led_initialise(); par_initialise(); vehicle_initialise(); net_initialise(); CHECKPOINT(0x21) // Startup sequence... // Holding the RED led on, pulse out the firmware version on the GREEN led delay100(10); // Delay 1 second led_set(OVMS_LED_RED, OVMS_LED_ON); led_set(OVMS_LED_GRN, OVMS_LED_OFF); led_start(); delay100(10); // Delay 1.0 seconds led_set(OVMS_LED_GRN, ovms_firmware[0]); led_start(); delay100(35); // Delay 3.5 seconds ClrWdt(); // Clear Watchdog Timer led_set(OVMS_LED_GRN, ovms_firmware[1]); led_start(); delay100(35); // Delay 3.5 seconds ClrWdt(); // Clear Watchdog Timer led_set(OVMS_LED_GRN, ovms_firmware[2]); led_start(); delay100(35); // Delay 3.5 seconds ClrWdt(); // Clear Watchdog Timer led_set(OVMS_LED_GRN, OVMS_LED_OFF); led_set(OVMS_LED_RED, OVMS_LED_OFF); led_start(); delay100(10); // Delay 1 second ClrWdt(); // Clear Watchdog Timer // Setup ready for the main loop led_set(OVMS_LED_GRN, OVMS_LED_OFF); led_start(); #ifdef OVMS_HW_V2 car_12vline = inputs_voltage()*10; car_12vline_ref = 0; #endif #ifdef OVMS_ACCMODULE acc_initialise(); #endif // Proceed to main loop y = 0; // Last TMR0H while (1) // Main Loop { CHECKPOINT(0x22) if ((vUARTIntStatus.UARTIntRxError) || (vUARTIntStatus.UARTIntRxOverFlow)) net_reset_async(); while (!vUARTIntStatus.UARTIntRxBufferEmpty) { CHECKPOINT(0x23) net_poll(); } CHECKPOINT(0x24) vehicle_idlepoll(); ClrWdt(); // Clear Watchdog Timer x = TMR0L; if (TMR0H >= 0x4c) // Timout ~1sec (actually 996ms) { TMR0H = 0; TMR0L = 0; // Reset timer CHECKPOINT(0x25) net_ticker(); CHECKPOINT(0x26) vehicle_ticker(); #ifdef OVMS_LOGGINGMODULE CHECKPOINT(0x27) logging_ticker(); #endif #ifdef OVMS_ACCMODULE CHECKPOINT(0x28) acc_ticker(); #endif } else if (TMR0H != y) { if ((TMR0H % 0x04) == 0) { CHECKPOINT(0x29) net_ticker10th(); CHECKPOINT(0x2A) vehicle_ticker10th(); CHECKPOINT(0x2B) } y = TMR0H; } }
//////////////////////////////////////////////////////////////////////// // vehicle_initialise() // This function is an entry point from the main() program loop, and // gives the vehicle framework an opportunity to initialise itself. // void vehicle_initialise(void) { char *p; vehicle_fn_init = NULL; vehicle_fn_poll0 = NULL; vehicle_fn_poll1 = NULL; vehicle_fn_ticker1 = NULL; vehicle_fn_ticker10 = NULL; vehicle_fn_ticker60 = NULL; vehicle_fn_ticker300 = NULL; vehicle_fn_ticker600 = NULL; vehicle_fn_ticker = NULL; vehicle_fn_ticker10th = NULL; vehicle_fn_idlepoll = NULL; vehicle_fn_commandhandler = NULL; vehicle_fn_smshandler = NULL; vehicle_fn_smsextensions = NULL; // Clear the internal GPS flag, unless specifically requested by the module net_fnbits &= ~(NET_FN_INTERNALGPS); p = par_get(PARAM_VEHICLETYPE); if (p == NULL) { car_type[0] = 0; // Car is undefined car_type[1] = 0; car_type[2] = 0; car_type[3] = 0; car_type[4] = 0; } #ifdef OVMS_CAR_TESLAROADSTER else if (memcmppgm2ram(p, (char const rom far*)"TR", 2) == 0) { void vehicle_teslaroadster_initialise(void); vehicle_teslaroadster_initialise(); } #endif #ifdef OVMS_CAR_VOLTAMPERA else if (memcmppgm2ram(p, (char const rom far*)"VA", 2) == 0) { void vehicle_voltampera_initialise(void); vehicle_voltampera_initialise(); } #endif #ifdef OVMS_CAR_RENAULTTWIZY else if (memcmppgm2ram(p, (char const rom far*)"RT", 2) == 0) { void vehicle_twizy_initialise(void); vehicle_twizy_initialise(); } #endif #ifdef OVMS_CAR_OBDII else if (memcmppgm2ram(p, (char const rom far*)"O2", 2) == 0) { void vehicle_obdii_initialise(void); vehicle_obdii_initialise(); } #endif #ifdef OVMS_CAR_THINKCITY else if (memcmppgm2ram(p, (char const rom far*)"TC", 2) == 0) { void vehicle_thinkcity_initialise(void); vehicle_thinkcity_initialise(); } #endif #ifdef OVMS_CAR_NISSANLEAF else if (memcmppgm2ram(p, (char const rom far*)"NL", 2) == 0) { void vehicle_nissanleaf_initialise(void); vehicle_nissanleaf_initialise(); } #endif #ifdef OVMS_CAR_NONE else { void vehicle_none_initialise(void); vehicle_none_initialise(); } #endif RCONbits.IPEN = 1; // Enable Interrupt Priority PIE3bits.RXB1IE = 1; // CAN Receive Buffer 1 Interrupt Enable bit PIE3bits.RXB0IE = 1; // CAN Receive Buffer 0 Interrupt Enable bit IPR3 = 0b00000011; // high priority interrupts for Buffers 0 and 1 p = par_get(PARAM_MILESKM); can_mileskm = *p; }
void par_getbase64(unsigned char param, void* dest, size_t length) { char *p = par_get(param); memset(dest,0,length); base64decode(p, dest); }
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; }
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); }