#include "esphome.h" #include #define WIFI_DELAY 15 class SolarUART : public PollingComponent, public Sensor{ public: SolarUART() : PollingComponent(250) {} // constructor Sensor *v_cell1 = new Sensor(); Sensor *v_cell2 = new Sensor(); Sensor *v_cell3 = new Sensor(); Sensor *v_cell4 = new Sensor(); Sensor *v_cell5 = new Sensor(); Sensor *v_cell6 = new Sensor(); Sensor *v_cell7 = new Sensor(); Sensor *v_cell8 = new Sensor(); Sensor *itemp = new Sensor(); Sensor *etemp = new Sensor(); Sensor *v_batt = new Sensor(); Sensor *i_batt = new Sensor(); Sensor *i_pv = new Sensor(); Sensor *p_pv = new Sensor(); Sensor *i_load = new Sensor(); Sensor *p_load = new Sensor(); Sensor *soc = new Sensor(); char rxbuff[2048]; uint16_t varsbms[100]; uint8_t startupcounter; uint16_t bsos; // backslash offset void setup() override { //Serial.setRxBufferSize(2048); startupcounter = 0; } void update() override { //ESP_LOGD("custom", "This is a custom debug message"); if (Serial.available() >= 2000) { delay(20); uint16_t avail = Serial.available(); bsos = 0; //ESP_LOGD("custom", "Serial available %d", avail); Serial.readBytes(rxbuff, Serial.available()); /*for (uint16_t i = 0; i < avail; i++) { rxbuff[i] = Serial.read(); // Single backslash appears as double backslash in char array, screwing up positioning if (((uint8_t)rxbuff[i]) == 92) { if (i < 1530) { ESP_LOGD("custom", "char at pos: %u %c %u +1 %c %u -1 %c %u ", i, rxbuff[i], (uint8_t)rxbuff[i], rxbuff[i+1], (uint8_t)rxbuff[i+1], rxbuff[i-1], (uint8_t)rxbuff[i-1]); } //i-=1; } }*/ rxbuff[avail+1] = '\0'; char* sloc = strstr(rxbuff, "var sbms="); if (sloc) { if(startupcounter > 10) { // discard first 10 pieces of data sloc+= 10; char* eloc = strstr(sloc, "var xsbms"); //ESP_LOGD("custom", "eloc var found at: %d", (eloc-sloc)); sloc[eloc-sloc-3] = '\0'; /*ESP_LOGD("custom", sloc); delay(WIFI_DELAY);*/ /*ESP_LOGD("custom", "Sloc length: %d", eloc-sloc); delay(WIFI_DELAY);*/ /*uint16_t j = 0; for (uint16_t i = 0; i < eloc-sloc-2; i++) { if (sloc[i] != '\\') { varsbms[j] = sloc[i] } }*/ /*ESP_LOGD("custom", "%" PRIu64 "/%" PRIu64 "/%" PRIu64 " %" PRIu64 ":%" PRIu64 ":%" PRIu64 " %" PRIu64 "%% C1: %" PRIu64 " C2: %" PRIu64 " C3: %" PRIu64 " C4: %" PRIu64 " C5: %" PRIu64 " C6: %" PRIu64 " C7: %" PRIu64 " C8: %" PRIu64 " IT: %" PRIu64 " ET: %" PRId64 " IBAT: %c%" PRIu64 " PV1: %" PRIu64 " PV2: %" PRIu64 " %x", dcomp(1, sloc, 0)+2000, dcomp(1, sloc, 1), dcomp(1, sloc, 2), dcomp(1, sloc, 3), dcomp(1, sloc, 4), dcomp(1, sloc, 5), dcomp(2, sloc, 6), dcomp(2, sloc, 8), dcomp(2, sloc, 10), dcomp(2, sloc, 12), dcomp(2, sloc, 14), dcomp(2, sloc, 16), dcomp(2, sloc, 18), dcomp(2, sloc, 20), dcomp(2, sloc, 22), (dcomp(2, sloc, 24)-450)/10, ((int64_t)(dcomp(2, sloc, 26))-450)/10, sloc[28], dcomp(3, sloc, 29), dcomp(3, sloc, 32), dcomp(3, sloc, 35), (uint16_t)dcomp(3, sloc, 56));*/ // ESP_LOGD("custom", "SBMS : %" PRIu64 " ", dcomp(1, sloc, 0)+2000); // ESP_LOGD("custom", "SBMS year: %" PRIu64 " ", dcomp(1, sloc, 0)+2000); // ESP_LOGD("custom", "SBMS year: %" PRIu64 " ", dcomp(1, sloc, 0)+2000); // ESP_LOGD("custom", "SBMS seconds: %" PRIu64 " ", dcomp(1, sloc, 5)); //ESP_LOGD("custom", "SBMS soc: %" PRIu64 " ", ); //ESP_LOGD("custom", sloc); //SoC->publish_state() //ESP_LOGD("custom", "SBMS var found at: %d", sloc); //ESP_LOGD("custom", "Rxbuff length: %d" , strlen(rxbuff)); //ESP_LOGD("custom", sloc); /*if ((dcomp(1, sloc, 5) == 57) || (dcomp(1, sloc, 5) == 56) || (dcomp(1, sloc, 5) == 58) || (dcomp(1, sloc, 5) == 0)) { //id(solarstring).publish_state(sloc); ESP_LOGD("custom", sloc); }*/ //delay(WIFI_DELAY); /*ESP_LOGD("custom", "%" PRIu64 "/%" PRIu64 "/%" PRIu64 " %" PRIu64 ":%" PRIu64 ":%" PRIu64 " ", dcomp(1, sloc, 0)+2000, dcomp(1, sloc, 1), dcomp(1, sloc, 2), dcomp(1, sloc, 3), dcomp(1, sloc, 4), dcomp(1, sloc, 5)); delay(WIFI_DELAY);*/ uint8_t year = dcomp(1, sloc, 0); uint8_t month = dcomp(1, sloc, 1); uint8_t day = dcomp(1, sloc, 2); uint8_t hour = dcomp(1, sloc, 3); uint8_t minute = dcomp(1, sloc, 4); uint8_t second = dcomp(1, sloc, 5); char uptimestring[20]; if (second == 30) { sprintf(uptimestring, "%u/%u/%u %u:%u:%u", year, month, day, hour, minute, second); id(sbms_uptime).publish_state(uptimestring); delay(WIFI_DELAY); } uint8_t soc_val = dcomp(2, sloc, 6); float vcell1 = ((float)dcomp(2, sloc, 8))/1000.0; float vcell2 = ((float)dcomp(2, sloc, 10))/1000.0; float vcell3 = ((float)dcomp(2, sloc, 12))/1000.0; float vcell4 = ((float)dcomp(2, sloc, 14))/1000.0; float vcell5 = ((float)dcomp(2, sloc, 16))/1000.0; float vcell6 = ((float)dcomp(2, sloc, 18))/1000.0; float vcell7 = ((float)dcomp(2, sloc, 20))/1000.0; float vcell8 = ((float)dcomp(2, sloc, 22))/1000.0; soc->publish_state(soc_val); delay(WIFI_DELAY); v_cell1->publish_state(vcell1); delay(WIFI_DELAY); v_cell2->publish_state(vcell2); delay(WIFI_DELAY); v_cell3->publish_state(vcell3); delay(WIFI_DELAY); v_cell4->publish_state(vcell4); delay(WIFI_DELAY); v_cell5->publish_state(vcell5); delay(WIFI_DELAY); v_cell6->publish_state(vcell6); delay(WIFI_DELAY); v_cell7->publish_state(vcell7); delay(WIFI_DELAY); v_cell8->publish_state(vcell8); delay(WIFI_DELAY); float internaltemp = (((float)dcomp(2, sloc, 24))-450)/10.0; float externaltemp = (((float)dcomp(2, sloc, 26))-450)/10.0; itemp->publish_state(internaltemp); delay(WIFI_DELAY); etemp->publish_state(externaltemp); delay(WIFI_DELAY); float vbatt_val = vcell1 + vcell2 + vcell3 + vcell4 + vcell5 + vcell6 + vcell7 + vcell8; v_batt->publish_state(vbatt_val); delay(WIFI_DELAY); // multiply by -1 based on the sign included in the string // need to get sign first otherwise a backslash could throw it off int8_t ibatt_mult = ((sloc[28+bsos] == '+')? 1 : -1); float ibatt_val = ((float)dcomp(3, sloc, 29))/1000.0 * ibatt_mult + 0.029; i_batt->publish_state(ibatt_val); delay(WIFI_DELAY); float ipv_val = ((float)dcomp(3, sloc, 32))/1000.0; i_pv->publish_state(ipv_val); delay(WIFI_DELAY); p_pv->publish_state(ipv_val * vbatt_val); delay(WIFI_DELAY); float iload_val = ipv_val - ibatt_val; i_load->publish_state(iload_val); delay(WIFI_DELAY); p_pv->publish_state(ipv_val * vbatt_val); delay(WIFI_DELAY); p_load->publish_state(iload_val * vbatt_val); delay(WIFI_DELAY); // Process data so that backslash offsets work properly, this data doesn't currently get used dcomp(3, sloc, 35); // PV2 dcomp(3, sloc, 38); // EXT dcomp(3, sloc, 41); // AD2 dcomp(3, sloc, 44); // AD3 dcomp(3, sloc, 47); // AD4 dcomp(3, sloc, 50); // HT1 dcomp(3, sloc, 53); // HT2 uint16_t flags_val = (uint16_t)dcomp(3, sloc, 56); if (!(flags_val&0b1000000000000)) { // ESP_LOGD("custom", sloc); id(solarstring).publish_state(sloc); delay(WIFI_DELAY); } id(ov).publish_state(flags_val&0b1); delay(WIFI_DELAY); id(ovlk).publish_state(flags_val&0b10); delay(WIFI_DELAY); id(uv).publish_state(flags_val&0b100); delay(WIFI_DELAY); id(uvlk).publish_state(flags_val&0b1000); delay(WIFI_DELAY); id(iot).publish_state(flags_val&0b10000); delay(WIFI_DELAY); id(coc).publish_state(flags_val&0b100000); delay(WIFI_DELAY); id(doc).publish_state(flags_val&0b1000000); delay(WIFI_DELAY); id(dsc).publish_state(flags_val&0b10000000); delay(WIFI_DELAY); id(celf).publish_state(flags_val&0b100000000); delay(WIFI_DELAY); id(sopen).publish_state(flags_val&0b1000000000); delay(WIFI_DELAY); id(lvc).publish_state(flags_val&0b10000000000); delay(WIFI_DELAY); id(eccf).publish_state(flags_val&0b100000000000); delay(WIFI_DELAY); id(cfet).publish_state(flags_val&0b1000000000000); delay(WIFI_DELAY); id(eoc).publish_state(flags_val&0b10000000000000); delay(WIFI_DELAY); id(dfet).publish_state(flags_val&0b100000000000000); delay(WIFI_DELAY); // Decode S2 (balance data) // have to start past end of previous string since that one was manually terminated sloc = strstr(eloc+5, "var s2="); if (sloc) { //ESP_LOGD("custom", "sloc %d", sloc); /*eloc = strstr(sloc, "var dmppt"); if (eloc) { ESP_LOGD("custom", "sloc %d", sloc); ESP_LOGD("custom", sloc); } else { ESP_LOGD("custom", "no eloc"); } } else { ESP_LOGD("custom", "no sloc"); }*/ //ESP_LOGD("custom", "sloc8: %c", sloc[8]); id(cell1bal).publish_state(sloc[8] == '1'); delay(WIFI_DELAY); id(cell2bal).publish_state(sloc[10] == '1'); delay(WIFI_DELAY); id(cell3bal).publish_state(sloc[12] == '1'); delay(WIFI_DELAY); id(cell4bal).publish_state(sloc[14] == '1'); delay(WIFI_DELAY); id(cell5bal).publish_state(sloc[16] == '1'); delay(WIFI_DELAY); id(cell6bal).publish_state(sloc[18] == '1'); delay(WIFI_DELAY); id(cell7bal).publish_state(sloc[20] == '1'); delay(WIFI_DELAY); id(cell8bal).publish_state(sloc[22] == '1'); delay(WIFI_DELAY); } } else { startupcounter++; } } //sloc+= 10; //ESP_LOGD("custom", "eloc %d", eloc); //sloc[eloc-sloc] = '\0'; //ESP_LOGD("custom", "sloc %d eloc %d", eloc, sloc); //id(solarstring).publish_state(sloc); // Serial.parseInt(); // year // Serial.parseInt(); // month // Serial.parseInt(); // day // Serial.parseInt(); // hour // Serial.parseInt(); // minute // Serial.parseInt(); // second // Serial.read(); // comma before flags // if (Serial.read() == ',') { // flags->publish_state(0); // } else { // flags->publish_state(Serial.parseInt()); // } // float vcell1 = ((float)Serial.parseInt())/1000.0; // float vcell2 = ((float)Serial.parseInt())/1000.0; // Serial.parseInt(); // midcell // Serial.parseInt(); // midcell // Serial.parseInt(); // midcell // Serial.parseInt(); // midcell // float vcell3 = ((float)Serial.parseInt())/1000.0; // float vcell4 = ((float)Serial.parseInt())/1000.0; // float ibatt = ((float)Serial.parseInt())/10.0; // float ipv = ((float)Serial.parseInt())/10.0; // float vbatt = vcell1 + vcell2 + vcell3 + vcell4; // float iload = ipv-ibatt; // float pload = vbatt*iload; // float ppv = vbatt*ipv; // if (vbatt > 10 && vbatt < 16) { // v_cell1->publish_state(vcell1); // delay(10); // v_cell2->publish_state(vcell2); // delay(10); // v_cell3->publish_state(vcell3); // delay(10); // v_cell4->publish_state(vcell4); // delay(10); // v_batt->publish_state(vbatt); // delay(10); // i_batt->publish_state(ibatt); // delay(10); // i_pv->publish_state(ipv); // delay(10); // p_pv->publish_state(ppv); // delay(10); // i_load->publish_state(iload); // delay(10); // p_load->publish_state(pload); // delay(10); // } // 2nd to last battery // last is PV } } uint64_t dcomp(uint8_t nr, char* datain, uint16_t pos) { int8_t i; uint64_t decval; decval=0; for (i=nr-1; i>=0;i--) { if (datain[(pos+nr+bsos-1)-i] == 92) { //ESP_LOGD("custom", "char at pos: %u %c %u bsos: %d", (pos+nr+bsos-1)-i, datain[(pos+nr+bsos-1)-i], (uint8_t)datain[(pos+nr+bsos-1)-i], bsos); bsos++; //pos+=1; } decval=decval+((datain[(pos+nr+bsos-1)-i]-35)*pow(91,i)); } return decval; } }; /*uint16_t dcmp(uint8_t p, uint8_t s, char* d) { uint16_t xx = 0; for (uint16_t z=0; z