ConfigRecords.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ConfigRecords.h" | ||
| 2 | #include "Utils.h" | ||
| 3 | |||
| 4 | 5013 | bool ConfigReader::next(uint8_t &val) { | |
| 5 | 5013 | if(!this->readByte(val)) return false; | |
| 6 | 5012 | this->_last = val; | |
| 7 | 5012 | return true; | |
| 8 | } | ||
| 9 | 31 | void ConfigReader::endRecord() { | |
| 10 | 31 | if(!this->atRecordEnd()) this->seekChar(CFG_REC_END); | |
| 11 | 31 | } | |
| 12 | 6 | bool ConfigReader::seekChar(const char val) { | |
| 13 | uint8_t ch; | ||
| 14 | do { | ||
| 15 | 624 | if(!this->next(ch)) return false; | |
| 16 | 623 | } while(ch != static_cast<uint8_t>(val)); | |
| 17 | 5 | return true; | |
| 18 | } | ||
| 19 | 556 | bool ConfigReader::readString(char *buff, size_t len) { | |
| 20 | 556 | memset(buff, 0x00, len); | |
| 21 | 556 | if(this->atRecordEnd()) return false; | |
| 22 | 549 | size_t i = 0; | |
| 23 | uint8_t val; | ||
| 24 | 3741 | while(this->next(val)) { | |
| 25 | 3192 | if(val == CFG_REC_END || val == CFG_VALUE_SEP) { | |
| 26 | 549 | _rtrim(buff); | |
| 27 | 549 | return true; | |
| 28 | } | ||
| 29 | 2643 | if(i < len - 1) buff[i++] = val; | |
| 30 | } | ||
| 31 | ✗ | return false; | |
| 32 | } | ||
| 33 | 20 | bool ConfigReader::readFixedString(char *buff, size_t len) { | |
| 34 | 20 | memset(buff, 0x00, len); | |
| 35 | 20 | if(this->atRecordEnd()) return false; | |
| 36 | uint8_t val; | ||
| 37 | 420 | for(size_t i = 0; i < len - 1; i++) { | |
| 38 | 400 | if(!this->next(val)) return false; | |
| 39 | 400 | if(val == CFG_REC_END) { | |
| 40 | ✗ | _rtrim(buff); | |
| 41 | ✗ | return true; | |
| 42 | } | ||
| 43 | 400 | buff[i] = val; | |
| 44 | } | ||
| 45 | // The separator after the padding. | ||
| 46 | 20 | if(!this->next(val)) return false; | |
| 47 | 20 | _rtrim(buff); | |
| 48 | 20 | return true; | |
| 49 | } | ||
| 50 | 46 | bool ConfigReader::readVarString(char *buff, size_t len) { | |
| 51 | 46 | memset(buff, 0x00, len); | |
| 52 | 46 | if(this->atRecordEnd()) return false; | |
| 53 | 46 | uint8_t quotes = 0; | |
| 54 | 46 | size_t i = 0; | |
| 55 | uint8_t val; | ||
| 56 | 777 | while(this->next(val)) { | |
| 57 | 777 | if(val == CFG_REC_END || (val == CFG_VALUE_SEP && quotes >= 2)) { | |
| 58 | 46 | _rtrim(buff); | |
| 59 | 46 | return true; | |
| 60 | } | ||
| 61 | 731 | if(val == CFG_TOK_QUOTE) { | |
| 62 | 92 | quotes++; | |
| 63 | 92 | continue; | |
| 64 | } | ||
| 65 | 639 | if(i < len - 1) buff[i++] = val; | |
| 66 | } | ||
| 67 | ✗ | return false; | |
| 68 | } | ||
| 69 | 16 | int8_t ConfigReader::readInt8(const int8_t defVal) { | |
| 70 | char buff[5]; | ||
| 71 | 16 | if(this->readString(buff, sizeof(buff))) return static_cast<int8_t>(atoi(buff)); | |
| 72 | 4 | return defVal; | |
| 73 | } | ||
| 74 | 359 | uint8_t ConfigReader::readUInt8(const uint8_t defVal) { | |
| 75 | char buff[4]; | ||
| 76 | 359 | if(this->readString(buff, sizeof(buff))) return static_cast<uint8_t>(atoi(buff)); | |
| 77 | 3 | return defVal; | |
| 78 | } | ||
| 79 | 25 | uint16_t ConfigReader::readUInt16(const uint16_t defVal) { | |
| 80 | char buff[6]; | ||
| 81 | 25 | if(this->readString(buff, sizeof(buff))) return static_cast<uint16_t>(atoi(buff)); | |
| 82 | ✗ | return defVal; | |
| 83 | } | ||
| 84 | 77 | uint32_t ConfigReader::readUInt32(const uint32_t defVal) { | |
| 85 | char buff[11]; | ||
| 86 | 77 | if(this->readString(buff, sizeof(buff))) return static_cast<uint32_t>(strtoul(buff, nullptr, 10)); | |
| 87 | ✗ | return defVal; | |
| 88 | } | ||
| 89 | 38 | float ConfigReader::readFloat(const float defVal) { | |
| 90 | char buff[25]; | ||
| 91 | 38 | if(this->readString(buff, sizeof(buff))) return atof(buff); | |
| 92 | ✗ | return defVal; | |
| 93 | } | ||
| 94 | 40 | bool ConfigReader::readBool(const bool defVal) { | |
| 95 | char buff[6]; | ||
| 96 | 40 | if(this->readString(buff, sizeof(buff))) { | |
| 97 | 40 | switch(buff[0]) { | |
| 98 | 32 | case 't': | |
| 99 | case 'T': | ||
| 100 | case '1': | ||
| 101 | 32 | return true; | |
| 102 | 8 | default: | |
| 103 | 8 | return false; | |
| 104 | } | ||
| 105 | } | ||
| 106 | ✗ | return defVal; | |
| 107 | } | ||
| 108 | |||
| 109 | 1307 | bool ConfigWriter::writeChar(const char val) { | |
| 110 | 1307 | const uint8_t b = static_cast<uint8_t>(val); | |
| 111 | 2614 | return this->writeBytes(&b, 1); | |
| 112 | } | ||
| 113 | 761 | bool ConfigWriter::writeString(const char *val, size_t len, const char tok) { | |
| 114 | 761 | size_t slen = strlen(val); | |
| 115 | 761 | if(slen > 0 && !this->writeBytes(reinterpret_cast<const uint8_t *>(val), slen)) return false; | |
| 116 | // Pad the value to its fixed width. | ||
| 117 | 1121 | while(slen + 1 < len) { | |
| 118 | 360 | if(!this->writeChar(' ')) return false; | |
| 119 | 360 | slen++; | |
| 120 | } | ||
| 121 | 761 | if(tok != CFG_TOK_NONE) return this->writeChar(tok); | |
| 122 | ✗ | return true; | |
| 123 | } | ||
| 124 | 62 | bool ConfigWriter::writeVarString(const char *val, const char tok) { | |
| 125 | 62 | this->writeChar(CFG_TOK_QUOTE); | |
| 126 | 62 | const size_t slen = strlen(val); | |
| 127 | 62 | if(slen > 0 && !this->writeBytes(reinterpret_cast<const uint8_t *>(val), slen)) return false; | |
| 128 | 62 | this->writeChar(CFG_TOK_QUOTE); | |
| 129 | 62 | if(tok != CFG_TOK_NONE) return this->writeChar(tok); | |
| 130 | ✗ | return true; | |
| 131 | } | ||
| 132 | 9 | bool ConfigWriter::writeInt8(const int8_t val, const char tok) { | |
| 133 | char buff[5]; | ||
| 134 | 9 | snprintf(buff, sizeof(buff), "%4d", val); | |
| 135 | 18 | return this->writeString(buff, sizeof(buff), tok); | |
| 136 | } | ||
| 137 | 473 | bool ConfigWriter::writeUInt8(const uint8_t val, const char tok) { | |
| 138 | char buff[4]; | ||
| 139 | 473 | snprintf(buff, sizeof(buff), "%3u", val); | |
| 140 | 946 | return this->writeString(buff, sizeof(buff), tok); | |
| 141 | } | ||
| 142 | 41 | bool ConfigWriter::writeUInt16(const uint16_t val, const char tok) { | |
| 143 | char buff[6]; | ||
| 144 | 41 | snprintf(buff, sizeof(buff), "%5u", val); | |
| 145 | 82 | return this->writeString(buff, sizeof(buff), tok); | |
| 146 | } | ||
| 147 | 108 | bool ConfigWriter::writeUInt32(const uint32_t val, const char tok) { | |
| 148 | char buff[11]; | ||
| 149 | 108 | snprintf(buff, sizeof(buff), "%10u", static_cast<unsigned>(val)); | |
| 150 | 216 | return this->writeString(buff, sizeof(buff), tok); | |
| 151 | } | ||
| 152 | 49 | bool ConfigWriter::writeFloat(const float val, const uint8_t prec, const char tok) { | |
| 153 | char buff[20]; | ||
| 154 | 49 | snprintf(buff, sizeof(buff), "%*.*f", 7 + prec, prec, val); | |
| 155 | 98 | return this->writeString(buff, 8 + prec, tok); | |
| 156 | } | ||
| 157 | 54 | bool ConfigWriter::writeBool(const bool val, const char tok) { | |
| 158 | 54 | return this->writeString(val ? "true" : "false", 6, tok); | |
| 159 | } | ||
| 160 | |||
| 161 | 2 | bool writeConfigHeader(ConfigWriter &w, const config_header_t &header) { | |
| 162 | 2 | w.writeUInt8(header.version); | |
| 163 | 2 | w.writeUInt8(header.length); | |
| 164 | 2 | w.writeUInt16(header.roomRecordSize); | |
| 165 | 2 | w.writeUInt8(header.roomRecords); | |
| 166 | 2 | w.writeUInt16(header.shadeRecordSize); | |
| 167 | 2 | w.writeUInt8(header.shadeRecords); | |
| 168 | 2 | w.writeUInt16(header.groupRecordSize); | |
| 169 | 2 | w.writeUInt8(header.groupRecords); | |
| 170 | 2 | w.writeUInt16(header.repeaterRecordSize); | |
| 171 | 2 | w.writeUInt8(header.repeaterRecords); | |
| 172 | 2 | w.writeUInt16(header.settingsRecordSize); | |
| 173 | 2 | w.writeUInt16(header.netRecordSize); | |
| 174 | 2 | w.writeUInt16(header.transRecordSize); | |
| 175 | 2 | return w.writeString(header.serverId, sizeof(header.serverId), CFG_REC_END); | |
| 176 | } | ||
| 177 | 2 | bool readConfigHeader(ConfigReader &r, config_header_t &header) { | |
| 178 | 2 | r.beginRecord(); | |
| 179 | 2 | header.version = r.readUInt8(header.version); | |
| 180 | 2 | header.length = r.readUInt8(0); | |
| 181 | 2 | if(header.version >= 19) { | |
| 182 | 1 | header.roomRecordSize = r.readUInt16(header.roomRecordSize); | |
| 183 | 1 | header.roomRecords = r.readUInt8(header.roomRecords); | |
| 184 | } | ||
| 185 | 2 | if(header.version >= 13) header.shadeRecordSize = r.readUInt16(header.shadeRecordSize); | |
| 186 | 1 | else header.shadeRecordSize = r.readUInt8(static_cast<uint8_t>(header.shadeRecordSize)); | |
| 187 | 2 | header.shadeRecords = r.readUInt8(header.shadeRecords); | |
| 188 | 2 | if(header.version > 10) { | |
| 189 | 2 | if(header.version >= 13) header.groupRecordSize = r.readUInt16(header.groupRecordSize); | |
| 190 | 1 | else header.groupRecordSize = r.readUInt8(header.groupRecordSize); | |
| 191 | 2 | header.groupRecords = r.readUInt8(header.groupRecords); | |
| 192 | } | ||
| 193 | 2 | if(header.version >= 21) { | |
| 194 | 1 | header.repeaterRecordSize = r.readUInt16(header.repeaterRecordSize); | |
| 195 | 1 | header.repeaterRecords = r.readUInt8(header.repeaterRecords); | |
| 196 | } | ||
| 197 | 2 | if(header.version > 13) { | |
| 198 | 1 | header.settingsRecordSize = r.readUInt16(header.settingsRecordSize); | |
| 199 | 1 | header.netRecordSize = r.readUInt16(header.netRecordSize); | |
| 200 | 1 | header.transRecordSize = r.readUInt16(header.transRecordSize); | |
| 201 | 1 | r.readString(header.serverId, sizeof(header.serverId)); | |
| 202 | } | ||
| 203 | 2 | return true; | |
| 204 | } | ||
| 205 | |||
| 206 | 8 | bool writeRoomRecord(ConfigWriter &w, const room_record_t &rec) { | |
| 207 | 8 | w.writeUInt8(rec.roomId); | |
| 208 | 8 | w.writeString(rec.name, sizeof(rec.name)); | |
| 209 | 8 | return w.writeUInt8(static_cast<uint8_t>(rec.sortOrder), CFG_REC_END); | |
| 210 | } | ||
| 211 | 7 | bool readRoomRecord(ConfigReader &r, room_record_t &rec) { | |
| 212 | 7 | r.beginRecord(); | |
| 213 | 7 | rec.roomId = r.readUInt8(0); | |
| 214 | 7 | r.readFixedString(rec.name, sizeof(rec.name)); | |
| 215 | 7 | rec.sortOrder = static_cast<int8_t>(r.readUInt8(rec.roomId - 1)); | |
| 216 | 7 | r.endRecord(); | |
| 217 | 7 | return true; | |
| 218 | } | ||
| 219 | |||
| 220 | 5 | bool writeShadeRecord(ConfigWriter &w, const shade_record_t &rec) { | |
| 221 | 5 | w.writeUInt8(rec.shadeId); | |
| 222 | 5 | w.writeBool(rec.paired); | |
| 223 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.shadeType)); | |
| 224 | 5 | w.writeUInt32(rec.remoteAddress); | |
| 225 | 5 | w.writeString(rec.name, sizeof(rec.name)); | |
| 226 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.tiltType)); | |
| 227 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.proto)); | |
| 228 | 5 | w.writeUInt8(rec.bitLength); | |
| 229 | 5 | w.writeUInt32(rec.upTime); | |
| 230 | 5 | w.writeUInt32(rec.downTime); | |
| 231 | 5 | w.writeUInt32(rec.tiltTime); | |
| 232 | 5 | w.writeUInt16(rec.stepSize); | |
| 233 | 40 | for(uint8_t j = 0; j < SOMFY_MAX_LINKED_REMOTES; j++) w.writeUInt32(rec.linkedRemotes[j]); | |
| 234 | 5 | w.writeUInt16(rec.lastRollingCode); | |
| 235 | 5 | if(rec.shadeId != 255) { | |
| 236 | 4 | w.writeUInt8(rec.flags); | |
| 237 | 4 | w.writeFloat(rec.myPos, 5); | |
| 238 | 4 | w.writeFloat(rec.myTiltPos, 5); | |
| 239 | 4 | w.writeFloat(rec.currentPos, 5); | |
| 240 | 4 | w.writeFloat(rec.currentTiltPos, 5); | |
| 241 | } | ||
| 242 | else { | ||
| 243 | // A deleted shade is written cleared. | ||
| 244 | 1 | w.writeUInt8(0); | |
| 245 | 1 | w.writeFloat(-1.0f, 5); | |
| 246 | 1 | w.writeFloat(-1.0f, 5); | |
| 247 | 1 | w.writeFloat(0.0f, 5); | |
| 248 | 1 | w.writeFloat(0.0f, 5); | |
| 249 | } | ||
| 250 | 5 | w.writeBool(rec.flipCommands); | |
| 251 | 5 | w.writeBool(rec.flipPosition); | |
| 252 | 5 | w.writeUInt8(rec.repeats); | |
| 253 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.sortOrder)); | |
| 254 | 5 | w.writeUInt8(rec.gpioUp); | |
| 255 | 5 | w.writeUInt8(rec.gpioDown); | |
| 256 | 5 | w.writeUInt8(rec.gpioMy); | |
| 257 | 5 | w.writeUInt8(rec.gpioFlags); | |
| 258 | 5 | return w.writeUInt8(rec.roomId, CFG_REC_END); | |
| 259 | } | ||
| 260 | 7 | bool readShadeRecord(ConfigReader &r, const config_header_t &header, shade_record_t &rec) { | |
| 261 | 7 | const uint8_t ver = header.version; | |
| 262 | 7 | r.beginRecord(); | |
| 263 | 7 | rec.shadeId = r.readUInt8(255); | |
| 264 | 7 | rec.paired = r.readBool(false); | |
| 265 | 7 | rec.shadeType = static_cast<shade_types>(r.readUInt8(0)); | |
| 266 | 7 | rec.remoteAddress = r.readUInt32(0); | |
| 267 | 7 | r.readFixedString(rec.name, sizeof(rec.name)); | |
| 268 | 7 | if(ver < 3) rec.tiltType = r.readBool(false) ? tilt_types::none : tilt_types::tiltmotor; | |
| 269 | 6 | else rec.tiltType = static_cast<tilt_types>(r.readUInt8(0)); | |
| 270 | 7 | if(ver > 6) rec.proto = static_cast<radio_proto>(r.readUInt8(0)); | |
| 271 | 7 | if(ver > 1) rec.bitLength = r.readUInt8(56); | |
| 272 | 7 | rec.upTime = r.readUInt32(rec.upTime); | |
| 273 | 7 | rec.downTime = r.readUInt32(rec.downTime); | |
| 274 | 7 | rec.tiltTime = r.readUInt32(rec.tiltTime); | |
| 275 | 7 | if(ver > 5) rec.stepSize = r.readUInt16(100); | |
| 276 | // Before version 5 a shade had 5 linked remotes. | ||
| 277 | 7 | const uint8_t remotes = ver < 5 ? 5 : SOMFY_MAX_LINKED_REMOTES; | |
| 278 | 50 | for(uint8_t j = 0; j < remotes; j++) rec.linkedRemotes[j] = r.readUInt32(0); | |
| 279 | 7 | rec.lastRollingCode = r.readUInt16(0); | |
| 280 | 7 | if(ver > 7) rec.flags = r.readUInt8(0); | |
| 281 | 7 | if(ver < 4) rec.myPos = static_cast<float>(r.readUInt8(255)); | |
| 282 | else { | ||
| 283 | 6 | rec.myPos = r.readFloat(-1); | |
| 284 | 6 | rec.myTiltPos = r.readFloat(-1); | |
| 285 | } | ||
| 286 | 7 | if(rec.myPos > 100 || rec.myPos < 0) rec.myPos = -1; | |
| 287 | 7 | if(rec.myTiltPos > 100 || rec.myTiltPos < 0) rec.myTiltPos = -1; | |
| 288 | 7 | rec.currentPos = r.readFloat(0); | |
| 289 | 7 | rec.currentTiltPos = r.readFloat(0); | |
| 290 | 7 | if(rec.tiltType == tilt_types::none || rec.shadeType != shade_types::blind) { | |
| 291 | 4 | rec.myTiltPos = -1; | |
| 292 | 4 | rec.currentTiltPos = 0; | |
| 293 | 4 | rec.tiltType = tilt_types::none; | |
| 294 | } | ||
| 295 | 7 | if(ver < 3) { | |
| 296 | // Positions were fractions. | ||
| 297 | 1 | rec.currentPos = rec.currentPos * 100; | |
| 298 | 1 | rec.currentTiltPos = rec.currentTiltPos * 100; | |
| 299 | } | ||
| 300 | 7 | if(ver >= 9) rec.flipCommands = r.readBool(false); | |
| 301 | 7 | if(ver >= 10) rec.flipPosition = r.readBool(false); | |
| 302 | 7 | if(ver >= 12) rec.repeats = r.readUInt8(1); | |
| 303 | 7 | if(ver >= 13) rec.sortOrder = static_cast<int8_t>(r.readUInt8(rec.shadeId - 1)); | |
| 304 | 3 | else rec.sortOrder = static_cast<int8_t>(rec.shadeId - 1); | |
| 305 | 7 | if(ver > 14) { | |
| 306 | 3 | rec.gpioUp = r.readUInt8(rec.gpioUp); | |
| 307 | 3 | rec.gpioDown = r.readUInt8(rec.gpioDown); | |
| 308 | } | ||
| 309 | 7 | if(ver > 15) rec.gpioMy = r.readUInt8(rec.gpioMy); | |
| 310 | 7 | if(ver > 16) rec.gpioFlags = r.readUInt8(rec.gpioFlags); | |
| 311 | 7 | if(rec.shadeId != 255 && rec.tiltType == tilt_types::tiltonly) { | |
| 312 | // A tilt only shade is always all the way down. | ||
| 313 | ✗ | rec.currentPos = 100.0f; | |
| 314 | ✗ | rec.myPos = 100.0f; | |
| 315 | } | ||
| 316 | 7 | if(ver >= 19) rec.roomId = r.readUInt8(0); | |
| 317 | 7 | r.endRecord(); | |
| 318 | 7 | return true; | |
| 319 | } | ||
| 320 | |||
| 321 | 5 | bool writeGroupRecord(ConfigWriter &w, const group_record_t &rec) { | |
| 322 | 5 | w.writeUInt8(rec.groupId); | |
| 323 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.groupType)); | |
| 324 | 5 | w.writeUInt32(rec.remoteAddress); | |
| 325 | 5 | w.writeString(rec.name, sizeof(rec.name)); | |
| 326 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.proto)); | |
| 327 | 5 | w.writeUInt8(rec.bitLength); | |
| 328 | 165 | for(uint8_t j = 0; j < SOMFY_MAX_GROUPED_SHADES; j++) w.writeUInt8(rec.linkedShades[j]); | |
| 329 | 5 | w.writeUInt8(rec.repeats); | |
| 330 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.sortOrder)); | |
| 331 | 5 | w.writeBool(rec.flipCommands); | |
| 332 | 5 | w.writeUInt8(rec.roomId); | |
| 333 | 5 | return w.writeUInt16(rec.lastRollingCode, CFG_REC_END); | |
| 334 | } | ||
| 335 | 6 | bool readGroupRecord(ConfigReader &r, const config_header_t &header, group_record_t &rec) { | |
| 336 | 6 | const uint8_t ver = header.version; | |
| 337 | 6 | r.beginRecord(); | |
| 338 | 6 | rec.groupId = r.readUInt8(255); | |
| 339 | 6 | rec.groupType = static_cast<group_types>(r.readUInt8(0)); | |
| 340 | 6 | rec.remoteAddress = r.readUInt32(0); | |
| 341 | 6 | r.readFixedString(rec.name, sizeof(rec.name)); | |
| 342 | 6 | rec.proto = static_cast<radio_proto>(r.readUInt8(0)); | |
| 343 | 6 | rec.bitLength = r.readUInt8(56); | |
| 344 | // Version 23 put the rolling code here, version 24 at the end. | ||
| 345 | 6 | if(ver == 23) rec.lastRollingCode = r.readUInt16(0); | |
| 346 | 6 | rec.hasRollingCode = ver >= 23; | |
| 347 | 6 | memset(rec.linkedShades, 0x00, sizeof(rec.linkedShades)); | |
| 348 | 6 | uint8_t linked = 0; | |
| 349 | 198 | for(uint8_t j = 0; j < SOMFY_MAX_GROUPED_SHADES; j++) { | |
| 350 | 192 | const uint8_t shadeId = r.readUInt8(0); | |
| 351 | 192 | if(shadeId > 0) rec.linkedShades[linked++] = shadeId; | |
| 352 | } | ||
| 353 | 6 | if(ver >= 12) rec.repeats = r.readUInt8(1); | |
| 354 | 6 | if(ver >= 13) rec.sortOrder = static_cast<int8_t>(r.readUInt8(rec.groupId - 1)); | |
| 355 | 2 | else rec.sortOrder = static_cast<int8_t>(rec.groupId - 1); | |
| 356 | 6 | if(ver >= 18) rec.flipCommands = r.readBool(false); | |
| 357 | 6 | if(ver >= 19) rec.roomId = r.readUInt8(0); | |
| 358 | 6 | if(ver >= 24) rec.lastRollingCode = r.readUInt16(0); | |
| 359 | 6 | r.endRecord(); | |
| 360 | 6 | return true; | |
| 361 | } | ||
| 362 | |||
| 363 | 1 | bool writeRepeaterRecord(ConfigWriter &w, const uint32_t (&repeaters)[SOMFY_MAX_REPEATERS]) { | |
| 364 | 8 | for(uint8_t i = 0; i < SOMFY_MAX_REPEATERS; i++) | |
| 365 | 7 | w.writeUInt32(repeaters[i], i == SOMFY_MAX_REPEATERS - 1 ? CFG_REC_END : CFG_VALUE_SEP); | |
| 366 | 1 | return true; | |
| 367 | } | ||
| 368 | ✗ | bool readRepeaterRecord(ConfigReader &r, uint32_t (&repeaters)[SOMFY_MAX_REPEATERS]) { | |
| 369 | ✗ | r.beginRecord(); | |
| 370 | ✗ | for(uint8_t i = 0; i < SOMFY_MAX_REPEATERS; i++) repeaters[i] = r.readUInt32(0); | |
| 371 | ✗ | r.endRecord(); | |
| 372 | ✗ | return true; | |
| 373 | } | ||
| 374 | |||
| 375 | 2 | bool writeSettingsRecord(ConfigWriter &w, const settings_record_t &rec) { | |
| 376 | 2 | w.writeVarString(rec.fwVersion); | |
| 377 | 2 | w.writeVarString(rec.hostname); | |
| 378 | 2 | w.writeVarString(rec.ntpServer); | |
| 379 | 2 | w.writeVarString(rec.posixZone); | |
| 380 | 2 | w.writeBool(rec.ssdpBroadcast); | |
| 381 | 2 | return w.writeBool(rec.checkForUpdate, CFG_REC_END); | |
| 382 | } | ||
| 383 | 3 | bool readSettingsRecord(ConfigReader &r, const config_header_t &header, settings_record_t &rec) { | |
| 384 | 3 | r.beginRecord(); | |
| 385 | 3 | r.readVarString(rec.fwVersion, sizeof(rec.fwVersion)); | |
| 386 | 3 | r.readVarString(rec.hostname, sizeof(rec.hostname)); | |
| 387 | 3 | r.readVarString(rec.ntpServer, sizeof(rec.ntpServer)); | |
| 388 | 3 | r.readVarString(rec.posixZone, sizeof(rec.posixZone)); | |
| 389 | 3 | rec.ssdpBroadcast = r.readBool(false); | |
| 390 | 3 | if(header.version >= 20) rec.checkForUpdate = r.readBool(true); | |
| 391 | 3 | r.endRecord(); | |
| 392 | 3 | return true; | |
| 393 | } | ||
| 394 | |||
| 395 | 6 | bool writeNetRecord(ConfigWriter &w, const net_record_t &rec, bool withEthernet) { | |
| 396 | 6 | w.writeUInt8(rec.connType); | |
| 397 | 6 | w.writeBool(rec.dhcp); | |
| 398 | 6 | w.writeVarString(rec.ip); | |
| 399 | 6 | w.writeVarString(rec.gateway); | |
| 400 | 6 | w.writeVarString(rec.subnet); | |
| 401 | 6 | w.writeVarString(rec.dns1); | |
| 402 | 6 | w.writeVarString(rec.dns2); | |
| 403 | 6 | w.writeVarString(rec.mqttProtocol); | |
| 404 | 6 | w.writeVarString(rec.mqttHostname); | |
| 405 | 6 | w.writeUInt16(rec.mqttPort); | |
| 406 | 6 | w.writeBool(rec.mqttPubDisco); | |
| 407 | 6 | w.writeVarString(rec.mqttRootTopic); | |
| 408 | 6 | w.writeVarString(rec.mqttDiscoTopic); | |
| 409 | 6 | if(!withEthernet) return w.writeUInt8(0, CFG_REC_END); | |
| 410 | 1 | w.writeUInt8(rec.ethBoardType); | |
| 411 | 1 | w.writeUInt8(rec.ethPhyType); | |
| 412 | 1 | w.writeUInt8(rec.ethClkMode); | |
| 413 | 1 | w.writeInt8(rec.ethPhyAddress); | |
| 414 | 1 | w.writeInt8(rec.ethPWRPin); | |
| 415 | 1 | w.writeInt8(rec.ethMDCPin); | |
| 416 | 1 | return w.writeInt8(rec.ethMDIOPin, CFG_REC_END); | |
| 417 | } | ||
| 418 | 4 | bool readNetRecord(ConfigReader &r, const config_header_t &header, net_record_t &rec, bool withEthernet) { | |
| 419 | 4 | r.beginRecord(); | |
| 420 | 4 | rec.connType = r.readUInt8(0); | |
| 421 | 4 | rec.dhcp = r.readBool(true); | |
| 422 | 4 | r.readVarString(rec.ip, sizeof(rec.ip)); | |
| 423 | 4 | r.readVarString(rec.gateway, sizeof(rec.gateway)); | |
| 424 | 4 | r.readVarString(rec.subnet, sizeof(rec.subnet)); | |
| 425 | 4 | r.readVarString(rec.dns1, sizeof(rec.dns1)); | |
| 426 | 4 | r.readVarString(rec.dns2, sizeof(rec.dns2)); | |
| 427 | 4 | if(header.version >= 22) { | |
| 428 | 3 | r.readVarString(rec.mqttProtocol, sizeof(rec.mqttProtocol)); | |
| 429 | 3 | r.readVarString(rec.mqttHostname, sizeof(rec.mqttHostname)); | |
| 430 | 3 | rec.mqttPort = r.readUInt16(1883); | |
| 431 | 3 | rec.mqttPubDisco = r.readBool(false); | |
| 432 | 3 | r.readVarString(rec.mqttRootTopic, sizeof(rec.mqttRootTopic)); | |
| 433 | 3 | r.readVarString(rec.mqttDiscoTopic, sizeof(rec.mqttDiscoTopic)); | |
| 434 | } | ||
| 435 | 4 | if(withEthernet) { | |
| 436 | 3 | rec.ethBoardType = r.readUInt8(1); | |
| 437 | 3 | rec.ethPhyType = r.readUInt8(0); | |
| 438 | 3 | rec.ethClkMode = r.readUInt8(0); | |
| 439 | 3 | rec.ethPhyAddress = r.readInt8(1); | |
| 440 | 3 | rec.ethPWRPin = r.readInt8(1); | |
| 441 | 3 | rec.ethMDCPin = r.readInt8(16); | |
| 442 | 3 | rec.ethMDIOPin = r.readInt8(23); | |
| 443 | } | ||
| 444 | 4 | r.endRecord(); | |
| 445 | 4 | return true; | |
| 446 | } | ||
| 447 | |||
| 448 | 5 | bool writeTransRecord(ConfigWriter &w, const trans_record_t &rec) { | |
| 449 | 5 | w.writeBool(rec.enabled); | |
| 450 | 5 | w.writeUInt8(static_cast<uint8_t>(rec.proto)); | |
| 451 | 5 | w.writeUInt8(rec.type); | |
| 452 | 5 | w.writeUInt8(rec.SCKPin); | |
| 453 | 5 | w.writeUInt8(rec.CSNPin); | |
| 454 | 5 | w.writeUInt8(rec.MOSIPin); | |
| 455 | 5 | w.writeUInt8(rec.MISOPin); | |
| 456 | 5 | w.writeUInt8(rec.TXPin); | |
| 457 | 5 | w.writeUInt8(rec.RXPin); | |
| 458 | 5 | w.writeFloat(rec.frequency, 3); | |
| 459 | 5 | w.writeFloat(rec.rxBandwidth, 2); | |
| 460 | 5 | w.writeFloat(rec.deviation, 2); | |
| 461 | 5 | w.writeInt8(rec.txPower); | |
| 462 | 5 | return w.writeBool(rec.noiseDetection, CFG_REC_END); | |
| 463 | } | ||
| 464 | 4 | bool readTransRecord(ConfigReader &r, trans_record_t &rec) { | |
| 465 | 4 | r.beginRecord(); | |
| 466 | 4 | rec.enabled = r.readBool(false); | |
| 467 | 4 | rec.proto = static_cast<radio_proto>(r.readUInt8(0)); | |
| 468 | 4 | rec.type = r.readUInt8(56); | |
| 469 | 4 | rec.SCKPin = r.readUInt8(rec.SCKPin); | |
| 470 | 4 | rec.CSNPin = r.readUInt8(rec.CSNPin); | |
| 471 | 4 | rec.MOSIPin = r.readUInt8(rec.MOSIPin); | |
| 472 | 4 | rec.MISOPin = r.readUInt8(rec.MISOPin); | |
| 473 | 4 | rec.TXPin = r.readUInt8(rec.TXPin); | |
| 474 | 4 | rec.RXPin = r.readUInt8(rec.RXPin); | |
| 475 | 4 | rec.frequency = r.readFloat(rec.frequency); | |
| 476 | 4 | rec.rxBandwidth = r.readFloat(rec.rxBandwidth); | |
| 477 | 4 | rec.deviation = r.readFloat(rec.deviation); | |
| 478 | 4 | rec.txPower = r.readInt8(rec.txPower); | |
| 479 | 4 | rec.noiseDetection = r.readBool(false); | |
| 480 | 4 | r.endRecord(); | |
| 481 | 4 | return true; | |
| 482 | } | ||
| 483 | |||
| 484 | 3 | bool skipRecords(ConfigReader &r, uint32_t count) { | |
| 485 | 6 | for(uint32_t i = 0; i < count; i++) { | |
| 486 | 4 | r.beginRecord(); | |
| 487 | 4 | if(!r.seekChar(CFG_REC_END)) return false; | |
| 488 | } | ||
| 489 | 2 | return true; | |
| 490 | } | ||
| 491 |