mirror of https://github.com/lumapu/ahoy.git
				
				
			
			
			
				Browse Source
			
			
			
			
				
		* slim definitions of fields and units * prepared multi inverter setup (not finished now)pull/8/head
				 17 changed files with 829 additions and 688 deletions
			
			
		| @ -0,0 +1,38 @@ | |||
| #ifndef __DEBUG_H__ | |||
| #define __DEBUG_H__ | |||
| 
 | |||
| #ifdef NDEBUG | |||
|   #define DPRINT(str) | |||
| #else | |||
| 
 | |||
| #ifndef DSERIAL | |||
|   #define DSERIAL Serial | |||
| #endif | |||
| 
 | |||
|   template <class T> | |||
|   inline void DPRINT(T str) { DSERIAL.print(str); } | |||
|   template <class T> | |||
|   inline void DPRINTLN(T str) { DPRINT(str); DPRINT(F("\r\n")); } | |||
|   inline void DHEX(uint8_t b) { | |||
|     if( b<0x10 ) DSERIAL.print('0'); | |||
|     DSERIAL.print(b,HEX); | |||
|   } | |||
|   inline void DHEX(uint16_t b) { | |||
|     if( b<0x10 ) DSERIAL.print(F("000")); | |||
|     else if( b<0x100 ) DSERIAL.print(F("00")); | |||
|     else if( b<0x1000 ) DSERIAL.print(F("0")); | |||
|     DSERIAL.print(b,HEX); | |||
|   } | |||
|   inline void DHEX(uint32_t b) { | |||
|     if( b<0x10 ) DSERIAL.print(F("0000000")); | |||
|     else if( b<0x100 ) DSERIAL.print(F("000000")); | |||
|     else if( b<0x1000 ) DSERIAL.print(F("00000")); | |||
|     else if( b<0x10000 ) DSERIAL.print(F("0000")); | |||
|     else if( b<0x100000 ) DSERIAL.print(F("000")); | |||
|     else if( b<0x1000000 ) DSERIAL.print(F("00")); | |||
|     else if( b<0x10000000 ) DSERIAL.print(F("0")); | |||
|     DSERIAL.print(b,HEX); | |||
|   } | |||
| #endif | |||
| 
 | |||
| #endif /*__DEBUG_H__*/ | |||
| @ -1,130 +0,0 @@ | |||
| #include "eep.h" | |||
| #include <EEPROM.h> | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| eep::eep() { | |||
|     EEPROM.begin(500); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| eep::~eep() { | |||
|     EEPROM.end(); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::read(uint32_t addr, char *str, uint8_t length) { | |||
|     for(uint8_t i = 0; i < length; i ++) { | |||
|         *(str++) = (char)EEPROM.read(addr++); | |||
|     } | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::read(uint32_t addr, float *value) { | |||
|     uint8_t *p = (uint8_t*)value; | |||
|     for(uint8_t i = 0; i < 4; i ++) { | |||
|         *(p++) = (uint8_t)EEPROM.read(addr++); | |||
|     } | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::read(uint32_t addr, bool *value) { | |||
|     uint8_t intVal = 0x00; | |||
|     intVal = EEPROM.read(addr++); | |||
|     *value = (intVal == 0x01); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::read(uint32_t addr, uint8_t *value) { | |||
|     *value = (EEPROM.read(addr++)); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::read(uint32_t addr, uint8_t data[], uint8_t length) { | |||
|     for(uint8_t i = 0; i < length; i ++) { | |||
|         *(data++) = EEPROM.read(addr++); | |||
|     } | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::read(uint32_t addr, uint16_t *value) { | |||
|     *value  = (EEPROM.read(addr++) << 8); | |||
|     *value |= (EEPROM.read(addr++)); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::read(uint32_t addr, uint32_t *value) { | |||
|     *value  = (EEPROM.read(addr++) << 24); | |||
|     *value |= (EEPROM.read(addr++) << 16); | |||
|     *value |= (EEPROM.read(addr++) <<  8); | |||
|     *value |= (EEPROM.read(addr++)); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::write(uint32_t addr, const char *str, uint8_t length) { | |||
|     for(uint8_t i = 0; i < length; i ++) { | |||
|         EEPROM.write(addr++, str[i]); | |||
|     } | |||
|     EEPROM.commit(); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::write(uint32_t addr, uint8_t data[], uint8_t length) { | |||
|     for(uint8_t i = 0; i < length; i ++) { | |||
|         EEPROM.write(addr++, data[i]); | |||
|     } | |||
|     EEPROM.commit(); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::write(uint32_t addr, float value) { | |||
|     uint8_t *p = (uint8_t*)&value; | |||
|     for(uint8_t i = 0; i < 4; i ++) { | |||
|         EEPROM.write(addr++, p[i]); | |||
|     } | |||
|     EEPROM.commit(); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::write(uint32_t addr, bool value) { | |||
|     uint8_t intVal = (value) ? 0x01 : 0x00; | |||
|     EEPROM.write(addr++, intVal); | |||
|     EEPROM.commit(); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::write(uint32_t addr, uint8_t value) { | |||
|     EEPROM.write(addr++, value); | |||
|     EEPROM.commit(); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::write(uint32_t addr, uint16_t value) { | |||
|     EEPROM.write(addr++, (value >> 8) & 0xff); | |||
|     EEPROM.write(addr++, (value     ) & 0xff); | |||
|     EEPROM.commit(); | |||
| } | |||
| 
 | |||
| 
 | |||
| //-----------------------------------------------------------------------------
 | |||
| void eep::write(uint32_t addr, uint32_t value) { | |||
|     EEPROM.write(addr++, (value >> 24) & 0xff); | |||
|     EEPROM.write(addr++, (value >> 16) & 0xff); | |||
|     EEPROM.write(addr++, (value >>  8) & 0xff); | |||
|     EEPROM.write(addr++, (value      ) & 0xff); | |||
|     EEPROM.commit(); | |||
| } | |||
| @ -1,87 +0,0 @@ | |||
| #ifndef __HM1200_DECODE__ | |||
| #define __HM1200_DECODE__ | |||
| 
 | |||
| typedef struct { | |||
|     double u; | |||
|     double i; | |||
|     double p; | |||
|     uint16_t y_d; // yield day
 | |||
|     double y_t; // yield total
 | |||
| } ch_t; | |||
| 
 | |||
| typedef struct { | |||
|     ch_t ch_dc[4]; | |||
|     ch_t ch_ac; | |||
|     double temp; | |||
|     double pct; | |||
|     double acFreq; | |||
| } hoyData_t; | |||
| 
 | |||
| class hm1200Decode { | |||
|     public: | |||
|         hm1200Decode() { | |||
|             memset(&mData, 0, sizeof(hoyData_t)); | |||
|         } | |||
|         ~hm1200Decode() {} | |||
| 
 | |||
|         void convert(uint8_t buf[], uint8_t len) { | |||
|             switch(buf[0]) { | |||
|                 case 0x01: convCmd01(buf, len); break; | |||
|                 case 0x02: convCmd02(buf, len); break; | |||
|                 case 0x03: convCmd03(buf, len); break; | |||
|                 case 0x84: convCmd84(buf, len); break; | |||
|                 default: break; | |||
|             } | |||
|         } | |||
| 
 | |||
| 
 | |||
|         hoyData_t mData; | |||
| 
 | |||
|     private: | |||
|         void convCmd01(uint8_t buf[], uint8_t len) { | |||
|             mData.ch_dc[0].u   = ((buf[ 3] << 8)  | buf[ 4]) / 10.0f; | |||
|             mData.ch_dc[0].i   = ((buf[ 5] << 8)  | buf[ 6]) / 100.0f; | |||
|             mData.ch_dc[1].i   = ((buf[ 7] << 8)  | buf[ 8]) / 100.0f; | |||
|             mData.ch_dc[0].p   = ((buf[ 9] << 8)  | buf[10]) / 10.0f; | |||
|             mData.ch_dc[1].p   = ((buf[11] << 8)  | buf[12]) / 10.0f; | |||
|             mData.ch_dc[0].y_t = ((buf[13] << 24) | (buf[14] << 16) | |||
|                                 | (buf[15] << 8)  | buf[16]) / 1000.0f; | |||
|         } | |||
| 
 | |||
| 
 | |||
|         void convCmd02(uint8_t buf[], uint8_t len) { | |||
|             mData.ch_dc[1].y_t = ((buf[ 1] << 24) | (buf[ 2] << 16) | |||
|                                 | (buf[ 3] << 8)  | buf[ 4]) / 1000.0f; | |||
|             mData.ch_dc[0].y_d = ((buf[ 5] << 8)  | buf[ 6]); | |||
|             mData.ch_dc[1].y_d = ((buf[ 7] << 8)  | buf[ 8]); | |||
|             mData.ch_dc[1].u   = ((buf[ 9] << 8)  | buf[10]) / 10.0f; | |||
|             mData.ch_dc[2].i   = ((buf[11] << 8)  | buf[12]) / 100.0f; | |||
|             mData.ch_dc[3].i   = ((buf[13] << 8)  | buf[14]) / 100.0f; | |||
|             mData.ch_dc[2].p   = ((buf[15] << 8)  | buf[16]) / 10.0f; | |||
|         } | |||
| 
 | |||
| 
 | |||
|         void convCmd03(uint8_t buf[], uint8_t len) { | |||
|             mData.ch_dc[3].p   = ((buf[ 1] << 8)  | buf[ 2]) / 10.0f; | |||
|             mData.ch_dc[2].y_t = ((buf[ 3] << 24) | (buf[4] << 16) | |||
|                                 | (buf[ 5] << 8)  | buf[ 6]) / 1000.0f; | |||
|             mData.ch_dc[3].y_t = ((buf[ 7] << 24) | (buf[8] << 16) | |||
|                                 | (buf[ 9] << 8)  | buf[10]) / 1000.0f; | |||
|             mData.ch_dc[2].y_d = ((buf[11] << 8)  | buf[12]); | |||
|             mData.ch_dc[3].y_d = ((buf[13] << 8)  | buf[14]); | |||
|             mData.ch_ac.u      = ((buf[15] << 8)  | buf[16]) / 10.0f; | |||
|         } | |||
| 
 | |||
| 
 | |||
|         void convCmd84(uint8_t buf[], uint8_t len) { | |||
|             mData.acFreq   = ((buf[ 1] << 8) | buf[ 2]) / 100.0f; | |||
|             mData.ch_ac.p  = ((buf[ 3] << 8) | buf[ 4]) / 10.0f; | |||
|             mData.ch_ac.i  = ((buf[ 7] << 8) | buf[ 8]) / 100.0f; | |||
|             mData.pct      = ((buf[ 9] << 8) | buf[10]) / 10.0f; | |||
|             mData.temp     = ((buf[11] << 8) | buf[12]) / 10.0f; | |||
|         } | |||
| 
 | |||
|         // private member variables
 | |||
| }; | |||
| 
 | |||
| #endif /*__HM1200_DECODE__*/ | |||
| @ -0,0 +1,111 @@ | |||
| #ifndef __HM_INVERTERS_H__ | |||
| #define __HM_INVERTERS_H__ | |||
| 
 | |||
| #include "debug.h" | |||
| #include <cstdint> | |||
| 
 | |||
| // units
 | |||
| enum {UNIT_V = 0, UNIT_A, UNIT_W,  UNIT_WH, UNIT_KWH, UNIT_HZ, UNIT_C, UNIT_PCT}; | |||
| const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%"}; | |||
| 
 | |||
| // field types
 | |||
| enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, | |||
|         FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT}; | |||
| const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", | |||
|         "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct"}; | |||
| 
 | |||
| 
 | |||
| 
 | |||
| // CH0 is default channel (freq, ac, temp)
 | |||
| enum {CH0 = 0, CH1, CH2, CH3, CH4}; | |||
| enum {CMD01 = 0x01, CMD02, CMD03, CMD83 = 0x83, CMD84}; | |||
| 
 | |||
| enum {INV_TYPE_HM600 = 0, INV_TYPE_HM1200}; | |||
| 
 | |||
| 
 | |||
| typedef struct { | |||
|     uint8_t    fieldId; // field id
 | |||
|     uint8_t    unitId;  // uint id
 | |||
|     uint8_t    ch;      // channel 0 - 3
 | |||
|     uint8_t    cmdId;   // received command id
 | |||
|     uint8_t    start;   // pos of first byte in buffer
 | |||
|     uint8_t    num;     // number of bytes in buffer
 | |||
|     uint16_t   div;     // divisor
 | |||
| } byteAssign_t; | |||
| 
 | |||
| 
 | |||
| union serial_u { | |||
|     uint64_t u64; | |||
|     uint8_t  b[8]; | |||
| }; | |||
| 
 | |||
| typedef struct { | |||
|     uint8_t       id;       // unique id
 | |||
|     char          name[20]; // human readable name, eg. "HM-600.1"
 | |||
|     uint8_t       type;     // integer which refers to inverter type
 | |||
|     byteAssign_t* assign;   // type of inverter
 | |||
|     uint8_t       listLen;  // length of assignments
 | |||
|     serial_u      serial;   // serial number as on barcode
 | |||
|     serial_u      radioId;  // id converted to modbus
 | |||
| } inverter_t; | |||
| 
 | |||
| 
 | |||
| /**
 | |||
|  *  indices are built for the buffer starting with cmd-id in first byte | |||
|  *  (complete payload in buffer) | |||
|  * */ | |||
| 
 | |||
| //-------------------------------------
 | |||
| // HM600, HM700
 | |||
| //-------------------------------------
 | |||
| const byteAssign_t hm600assignment[] = { | |||
|     { FLD_UDC, UNIT_V,  CH1, CMD01, 14, 2, 10  }, | |||
|     { FLD_IDC, UNIT_A,  CH1, CMD01, 16, 2, 100 }, | |||
|     { FLD_PDC, UNIT_W,  CH1, CMD01, 18, 2, 10  }, | |||
|     { FLD_UDC, UNIT_V,  CH2, CMD01, 20, 2, 10  }, | |||
|     { FLD_IDC, UNIT_A,  CH2, CMD01, 22, 2, 100 }, | |||
|     { FLD_PDC, UNIT_W,  CH2, CMD01, 24, 2, 10  }, | |||
|     { FLD_YW,  UNIT_WH, CH0, CMD02, 12, 2, 1   }, | |||
|     { FLD_YT,  UNIT_WH, CH0, CMD02, 14, 4, 1   }, | |||
|     { FLD_YD,  UNIT_WH, CH1, CMD02, 18, 2, 1   }, | |||
|     { FLD_YD,  UNIT_WH, CH2, CMD02, 20, 2, 1   }, | |||
|     { FLD_UAC, UNIT_V,  CH0, CMD02, 22, 2, 10  }, | |||
|     { FLD_F,   UNIT_HZ, CH0, CMD02, 24, 2, 100 }, | |||
|     { FLD_IAC, UNIT_A,  CH0, CMD02, 26, 2, 10  }, | |||
|     { FLD_T,   UNIT_C,  CH0, CMD83, 18, 2, 10  } | |||
| }; | |||
| #define HM600_LIST_LEN     (sizeof(hm600assignment) / sizeof(byteAssign_t)) | |||
| 
 | |||
| 
 | |||
| //-------------------------------------
 | |||
| // HM1200, HM1500?
 | |||
| //-------------------------------------
 | |||
| const byteAssign_t hm1200assignment[] = { | |||
|     { FLD_UDC, UNIT_V,   CH1, CMD01,  3, 2, 10   }, | |||
|     { FLD_IDC, UNIT_A,   CH1, CMD01,  5, 2, 100  }, | |||
|     { FLD_IDC, UNIT_A,   CH2, CMD01,  7, 2, 100  }, | |||
|     { FLD_PDC, UNIT_W,   CH1, CMD01,  9, 2, 10   }, | |||
|     { FLD_PDC, UNIT_W,   CH2, CMD01, 11, 2, 10   }, | |||
|     { FLD_YT,  UNIT_KWH, CH1, CMD01, 13, 4, 1000 }, | |||
|     { FLD_YT,  UNIT_KWH, CH2, CMD02,  1, 4, 1000 }, | |||
|     { FLD_YD,  UNIT_WH,  CH1, CMD02,  5, 2, 1    }, | |||
|     { FLD_YD,  UNIT_WH,  CH2, CMD02,  7, 2, 1    }, | |||
|     { FLD_UDC, UNIT_V,   CH2, CMD02,  9, 2, 10   }, | |||
|     { FLD_IDC, UNIT_A,   CH3, CMD02, 11, 2, 100  }, | |||
|     { FLD_IDC, UNIT_A,   CH4, CMD02, 13, 2, 100  }, | |||
|     { FLD_PDC, UNIT_W,   CH3, CMD02, 15, 2, 10   }, | |||
|     { FLD_PDC, UNIT_W,   CH4, CMD03,  1, 2, 10   }, | |||
|     { FLD_YT,  UNIT_KWH, CH3, CMD03,  3, 4, 1000 }, | |||
|     { FLD_YT,  UNIT_KWH, CH4, CMD03,  7, 4, 1000 }, | |||
|     { FLD_YD,  UNIT_WH,  CH3, CMD03, 11, 2, 1    }, | |||
|     { FLD_YD,  UNIT_WH,  CH4, CMD03, 13, 2, 1    }, | |||
|     { FLD_UAC, UNIT_V,   CH0, CMD03, 15, 2, 10   }, | |||
|     { FLD_F,   UNIT_HZ,  CH0, CMD84,  1, 2, 100  }, | |||
|     { FLD_PAC, UNIT_W,   CH0, CMD84,  3, 2, 10   }, | |||
|     { FLD_IAC, UNIT_A,   CH0, CMD84,  7, 2, 100  }, | |||
|     { FLD_PCT, UNIT_PCT, CH0, CMD84,  9, 2, 10   }, | |||
|     { FLD_T,   UNIT_C,   CH0, CMD84, 11, 2, 10   } | |||
| }; | |||
| #define HM1200_LIST_LEN     (sizeof(hm1200assignment) / sizeof(byteAssign_t)) | |||
| 
 | |||
| #endif /*__HM_INVERTERS_H__*/ | |||
| @ -0,0 +1,149 @@ | |||
| #ifndef __HM_SYSTEM_H__ | |||
| #define __HM_SYSTEM_H__ | |||
| 
 | |||
| #include "hmInverters.h" | |||
| #include "hmRadio.h" | |||
| 
 | |||
| typedef struct { | |||
|     uint8_t sendCh; | |||
|     uint8_t packet[MAX_RF_PAYLOAD_SIZE]; | |||
| } packet_t; | |||
| 
 | |||
| 
 | |||
| template <class RADIO, class BUFFER, uint8_t MAX_INVERTER, class RECORDTYPE=float> | |||
| class HmSystem { | |||
|     public: | |||
|         typedef RADIO RadioType; | |||
|         RadioType Radio; | |||
|         typedef BUFFER BufferType; | |||
|         BufferType BufCtrl; | |||
| 
 | |||
|         HmSystem() { | |||
|             mNumInv = 0; | |||
|         } | |||
|         ~HmSystem() { | |||
|             // TODO: cleanup
 | |||
|         } | |||
| 
 | |||
|         inverter_t *addInverter(const char *name, uint64_t serial, uint8_t type) { | |||
|             if(MAX_INVERTER <= mNumInv) { | |||
|                 DPRINT("max number of inverters reached!"); | |||
|                 return NULL; | |||
|             } | |||
|             inverter_t *p = &mInverter[mNumInv]; | |||
|             p->id         = mNumInv++; | |||
|             p->serial.u64 = serial; | |||
|             p->type       = type; | |||
|             uint8_t len   = strlen(name); | |||
|             strncpy(p->name, name, (len > 20) ? 20 : len); | |||
|             getAssignment(p); | |||
|             toRadioId(p); | |||
| 
 | |||
|             if(NULL == p->assign) { | |||
|                 DPRINT("no assignment for type found!"); | |||
|                 return NULL; | |||
|             } | |||
|             else { | |||
|                 mRecord = new RECORDTYPE[p->listLen]; | |||
|                 memset(mRecord, 0, sizeof(RECORDTYPE) * p->listLen); | |||
|                 return p; | |||
|             } | |||
|         } | |||
| 
 | |||
|         inverter_t *findInverter(uint8_t buf[]) { | |||
|             inverter_t *p; | |||
|             for(uint8_t i = 0; i < mNumInv; i++) { | |||
|                 p = &mInverter[i]; | |||
|                 if((p->serial.b[3] == buf[0]) | |||
|                     && (p->serial.b[2] == buf[1]) | |||
|                     && (p->serial.b[1] == buf[2]) | |||
|                     && (p->serial.b[0] == buf[3])) | |||
|                     return p; | |||
|             } | |||
|             return NULL; | |||
|         } | |||
| 
 | |||
|         inverter_t *getInverterByPos(uint8_t pos) { | |||
|             if(mInverter[pos].serial.u64 != 0ULL) | |||
|                 return &mInverter[pos]; | |||
|             else | |||
|                 return NULL; | |||
|         } | |||
| 
 | |||
|         const char *getFieldName(inverter_t *p, uint8_t pos) { | |||
|             return fields[p->assign[pos].fieldId]; | |||
|         } | |||
| 
 | |||
|         const char *getUnit(inverter_t *p, uint8_t pos) { | |||
|             return units[p->assign[pos].unitId]; | |||
|         } | |||
| 
 | |||
|         uint64_t getSerial(inverter_t *p) { | |||
|             return p->serial.u64; | |||
|         } | |||
| 
 | |||
|         void updateSerial(inverter_t *p, uint64_t serial) { | |||
|             p->serial.u64 = serial; | |||
|         } | |||
| 
 | |||
|         uint8_t getChannel(inverter_t *p, uint8_t pos) { | |||
|             return p->assign[pos].ch; | |||
|         } | |||
| 
 | |||
|         uint8_t getCmdId(inverter_t *p, uint8_t pos) { | |||
|             return p->assign[pos].cmdId; | |||
|         } | |||
| 
 | |||
|         void addValue(inverter_t *p, uint8_t pos, uint8_t buf[]) { | |||
|             uint8_t ptr  = p->assign[pos].start; | |||
|             uint8_t end  = ptr + p->assign[pos].num; | |||
|             uint16_t div = p->assign[pos].div; | |||
| 
 | |||
|             uint32_t val = 0; | |||
|             do { | |||
|                 val <<= 8; | |||
|                 val |= buf[ptr]; | |||
|             } while(++ptr != end); | |||
| 
 | |||
|             mRecord[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); | |||
|         } | |||
| 
 | |||
|         RECORDTYPE getValue(inverter_t *p, uint8_t pos) { | |||
|             return mRecord[pos]; | |||
|         } | |||
| 
 | |||
|         uint8_t getNumInverters(void) { | |||
|             return mNumInv; | |||
|         } | |||
| 
 | |||
|     private: | |||
|         void toRadioId(inverter_t *p) { | |||
|             p->radioId.u64  = 0ULL; | |||
|             p->radioId.b[4] = p->serial.b[0]; | |||
|             p->radioId.b[3] = p->serial.b[1]; | |||
|             p->radioId.b[2] = p->serial.b[2]; | |||
|             p->radioId.b[1] = p->serial.b[3]; | |||
|             p->radioId.b[0] = 0x01; | |||
|         } | |||
| 
 | |||
|         void getAssignment(inverter_t *p) { | |||
|             if(INV_TYPE_HM600 == p->type) { | |||
|                 p->listLen = (uint8_t)(HM1200_LIST_LEN); | |||
|                 p->assign  = (byteAssign_t*)hm600assignment; | |||
|             } | |||
|             else if(INV_TYPE_HM1200 == p->type) { | |||
|                 p->listLen = (uint8_t)(HM1200_LIST_LEN); | |||
|                 p->assign  = (byteAssign_t*)hm1200assignment; | |||
|             } | |||
|             else { | |||
|                 p->listLen = 0; | |||
|                 p->assign  = NULL; | |||
|             } | |||
|         } | |||
| 
 | |||
|         inverter_t mInverter[MAX_INVERTER]; // TODO: only one inverter supported!!!
 | |||
|         uint8_t mNumInv; | |||
|         RECORDTYPE *mRecord; | |||
| }; | |||
| 
 | |||
| #endif /*__HM_SYSTEM_H__*/ | |||
| @ -1 +1 @@ | |||
| String setup_html = "<!doctype html><html><head><title>Setup - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body><h1>Setup</h1><div id=\"setup\" class=\"content\"><div id=\"content\"><p>                    Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.                </p><form method=\"post\" action=\"/save\"><p class=\"des\">WiFi</p><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"ssid\" value=\"{SSID}\" required/><span class=\"floating_label\">SSID</span></div><div class=\"inputWrp\"><input type=\"password\" class=\"inputText\" name=\"pwd\" value=\"{PWD}\" required/><span class=\"floating_label\">PASSWORD</span></div><p class=\"des\">Device Host Name</p><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"device\" value=\"{DEVICE}\" required/><span class=\"floating_label\">DEVICE NAME</span></div><p class=\"des\">Inverter</p><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"inv0Addr\" value=\"{INV0_ADDR}\" required/><span class=\"floating_label\">INVERTER 0 ADDRESS (eg. 11:22:33:44:55:66)</span></div><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"invInterval\" value=\"{INV_INTERVAL}\" required/><span class=\"floating_label\">INTERVAL (ms)</span></div><p class=\"des\">MQTT</p><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"mqttAddr\" value=\"{MQTT_ADDR}\" required/><span class=\"floating_label\">BROKER (Server IP)</span></div><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"mqttUser\" value=\"{MQTT_USER}\"/><span class=\"floating_label\">USERNAME (optional)</span></div><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"mqttPwd\" value=\"{MQTT_PWD}\"/><span class=\"floating_label\">PASSWORD (optional)</span></div><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"mqttTopic\" value=\"{MQTT_TOPIC}\" required/><span class=\"floating_label\">TOPIC</span></div><div class=\"inputWrp\"><input type=\"text\" class=\"inputText\" name=\"mqttInterval\" value=\"{MQTT_INTERVAL}\" required/><span class=\"floating_label\">INTERVAL (ms)</span></div><input type=\"checkbox\" class=\"cb\" name=\"reboot\"/><label for=\"reboot\">Reboot device after successful save</label><input type=\"submit\" value=\"save\" class=\"button\" /></form></div></div><div id=\"footer\"><p class=\"left\"><a href=\"/\">Home</a></p><p class=\"left\"><a href=\"/update\">Update Firmware</a></p><p class=\"right\">AHOY - {VERSION}</p></div></body></html>"; | |||
| String setup_html = "<!doctype html><html><head><title>Setup - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body><h1>Setup</h1><div id=\"setup\" class=\"content\"><div id=\"content\"><p>                    Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.                </p><form method=\"post\" action=\"/save\"><p class=\"des\">WiFi</p><label for=\"ssid\">SSID</label><input type=\"text\" class=\"text\" name=\"ssid\" value=\"{SSID}\"/><label for=\"pwd\">Password</label><input type=\"password\" class=\"text\" name=\"pwd\" value=\"{PWD}\"/><p class=\"des\">Device Host Name</p><label for=\"device\">Device Name</label><input type=\"text\" class=\"text\" name=\"device\" value=\"{DEVICE}\"/><p class=\"des\">Inverter</p>                    {INVERTERS}<br/><label for=\"invInterval\">Interval (ms)</label><input type=\"text\" class=\"text\" name=\"invInterval\" value=\"{INV_INTERVAL}\"/><p class=\"des\">MQTT</p><label for=\"mqttAddr\">Broker / Server IP</label><input type=\"text\" class=\"text\" name=\"mqttAddr\" value=\"{MQTT_ADDR}\"/><label for=\"mqttUser\">Username (optional)</label><input type=\"text\" class=\"text\" name=\"mqttUser\" value=\"{MQTT_USER}\"/><label for=\"mqttPwd\">Password (optional)</label><input type=\"text\" class=\"text\" name=\"mqttPwd\" value=\"{MQTT_PWD}\"/><label for=\"mqttTopic\">Topic</label><input type=\"text\" class=\"text\" name=\"mqttTopic\" value=\"{MQTT_TOPIC}\"/><label for=\"mqttInterval\">Interval (seconds)</label><input type=\"text\" class=\"text\" name=\"mqttInterval\" value=\"{MQTT_INTERVAL}\"/><p class=\"des\"> </p><input type=\"checkbox\" class=\"cb\" name=\"reboot\"/><label for=\"reboot\">Reboot device after successful save</label><input type=\"submit\" value=\"save\" class=\"button\" /></form></div></div><div id=\"footer\"><p class=\"left\"><a href=\"/\">Home</a></p><p class=\"left\"><a href=\"/update\">Update Firmware</a></p><p class=\"right\">AHOY - {VERSION}</p></div></body></html>"; | |||
|  | |||
| @ -1 +1 @@ | |||
| String style_css = "h1 { margin: 0; padding: 20pt; font-size: 22pt; color: #fff; background-color: #006ec0; display: block; text-transform: uppercase; } html, body { font-family: Arial; margin: 0; padding: 0; } p { text-align: justify; font-size: 13pt; } .des { font-size: 14pt; color: #006ec0; padding-bottom: 0px !important; } .fw { width: 60px; display: block; float: left; } .color { width: 50px; height: 50px; border: 1px solid #ccc; } .range { width: 300px; } a:link, a:visited { text-decoration: none; font-size: 13pt; color: #006ec0; } a:hover, a:focus { color: #f00; } #content { padding: 15px 15px 60px 15px; } #footer { position: fixed; bottom: 0px; height: 45px; background-color: #006ec0; width: 100%; } #footer p { color: #fff; padding-left: 20px; padding-right: 20px; font-size: 10pt !important; } #footer a { color: #fff; } #footer a:hover { color: #f00; } div.content { background-color: #fff; padding-bottom: 65px; overflow: hidden; } span.warn { display: inline-block; padding-left: 20px; color: #ff9900; font-style: italic; } input { padding: 10px; font-size: 13pt; } input.button { background-color: #006ec0; color: #fff; border: 0px; float: right; text-transform: uppercase; } input.cb { margin-bottom: 20px; } label { font-size: 14pt; } .left { float: left; } .right { float: right; } .inputWrp { position: relative; } .inputWrp .inputText { height: 35px; width: 90%; margin-bottom: 20px; border: 1px solid #ccc; border-top: none; border-right: none; } .inputWrp .floating_label { position: absolute; pointer-events: none; top: 20px; left: 10px; transition: 0.2s ease all; } .inputWrp input:focus ~ .floating_label, .inputWrp input:not(:focus):valid ~ .floating_label { top: 0px; left: 20px; font-size: 10px; color: blue; opacity: 1; } div.module { display: block; width: 250px; height: 410px; background-color: #006ec0; display: inline-block; position: relative; margin-right: 20px; margin-bottom: 20px; } div.module .value, div.module .info, div.module .header { color: #fff; display: block; width: 100%; text-align: center; } div.module .unit { font-size: 19px; margin-left: 10px; } div.module .value { margin-top: 20px; font-size: 30px; } div.module .info { margin-top: 3px; font-size: 10px; } div.module .header { background-color: #003c80; padding: 10px 0 10px 0; } "; | |||
| String style_css = "h1 { margin: 0; padding: 20pt; font-size: 22pt; color: #fff; background-color: #006ec0; display: block; text-transform: uppercase; } html, body { font-family: Arial; margin: 0; padding: 0; } p { text-align: justify; font-size: 13pt; } .des { margin-top: 35px; font-size: 14pt; color: #006ec0; } .subdes { font-size: 13pt; color: #006ec0; margin-left: 7px; } .fw { width: 60px; display: block; float: left; } .color { width: 50px; height: 50px; border: 1px solid #ccc; } .range { width: 300px; } a:link, a:visited { text-decoration: none; font-size: 13pt; color: #006ec0; } a:hover, a:focus { color: #f00; } #content { padding: 15px 15px 60px 15px; } #footer { position: fixed; bottom: 0px; height: 45px; background-color: #006ec0; width: 100%; } #footer p { color: #fff; padding-left: 20px; padding-right: 20px; font-size: 10pt !important; } #footer a { color: #fff; } div.content { background-color: #fff; padding-bottom: 65px; overflow: hidden; } input { padding: 7px; font-size: 13pt; } input.text, input.password { width: 70%; box-sizing: border-box; margin-bottom: 10px; /*float: right;*/ border: 1px solid #ccc; } input.button { background-color: #006ec0; color: #fff; border: 0px; float: right; text-transform: uppercase; } input.cb { margin-bottom: 20px; } label { width: 20%; display: inline-block; font-size: 12pt; padding-right: 10px; margin-left: 10px; } .left { float: left; } .right { float: right; } div.module { display: block; width: 250px; height: 410px; background-color: #006ec0; display: inline-block; position: relative; margin-right: 20px; margin-bottom: 20px; } div.module .value, div.module .info, div.module .header { color: #fff; display: block; width: 100%; text-align: center; } div.module .unit { font-size: 19px; margin-left: 10px; } div.module .value { margin-top: 20px; font-size: 30px; } div.module .info { margin-top: 3px; font-size: 10px; } div.module .header { background-color: #003c80; padding: 10px 0 10px 0; } "; | |||
|  | |||
					Loading…
					
					
				
		Reference in new issue