src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
5 / 5
100.0%
Branches:
-
-%
Functions:
5 / 5
100.0%

ConfigRecords.h
Line Branch Exec Source
1 #ifndef CONFIG_RECORDS_H
2 #define CONFIG_RECORDS_H
3 #include <Arduino.h>
4 #include "ConfigHeader.h"
5 #include "ShadeTypes.h"
6 #include "SomfyFrame.h"
7
8 // The records of shades.cfg and of a backup, and how they are written and
9 // read. The file is text: each value is padded to a fixed width and followed
10 // by a comma, strings that vary in length are quoted, and each record ends
11 // with a newline. Older versions of the file lack the values added since,
12 // and read as their defaults. Kept free of the file system and the shade
13 // model so every version can be unit tested on the PC (pio test -e native).
14
15 #define CFG_VALUE_SEP ','
16 #define CFG_REC_END '\n'
17 #define CFG_TOK_NONE 0x00
18 #define CFG_TOK_QUOTE '"'
19
20 #define SHADE_HDR_VER 24
21 #define SHADE_HDR_SIZE 76
22 #define SHADE_REC_SIZE 276
23 #define GROUP_REC_SIZE 200
24 #define ROOM_REC_SIZE 29
25 #define REPEATER_REC_SIZE 77
26 // Files written before 4.0 declare the transceiver record 74 bytes: it was
27 // left there when noiseDetection was added.
28 #define TRANS_REC_SIZE 80
29
30 // The sizes of the strings, which are those of the fields they are read into.
31 #define CFG_NAME_LEN 21
32 #define CFG_VERSION_LEN 24
33 #define CFG_HOSTNAME_LEN 32
34 #define CFG_NTP_SERVER_LEN 65
35 #define CFG_POSIX_ZONE_LEN 64
36 #define CFG_IP_LEN 24
37 #define CFG_MQTT_PROTOCOL_LEN 10
38 #define CFG_MQTT_HOSTNAME_LEN 65
39 #define CFG_MQTT_TOPIC_LEN 65
40
41 // Reads the values of a file. A record's values past its end read as their
42 // defaults, so a record shorter than expected never reads into the next one.
43 class ConfigReader {
44 private:
45 uint8_t _last = 0;
46 bool next(uint8_t &val);
47 public:
48 31 virtual ~ConfigReader() {}
49 // The next byte of the file; false at its end.
50 virtual bool readByte(uint8_t &val) = 0;
51 virtual uint32_t position() = 0;
52 39 void beginRecord() { _last = 0; }
53 // Moves past the rest of the record: the values a newer version added.
54 void endRecord();
55 653 bool atRecordEnd() const { return _last == CFG_REC_END; }
56 bool seekChar(const char val);
57 // A value up to the next separator, cut to fit buff.
58 bool readString(char *buff, size_t len);
59 // A value padded to len - 1 bytes, read whole so it may hold commas: a
60 // name.
61 bool readFixedString(char *buff, size_t len);
62 // A quoted value of any length, cut to fit buff.
63 bool readVarString(char *buff, size_t len);
64 int8_t readInt8(const int8_t defVal = 0);
65 uint8_t readUInt8(const uint8_t defVal = 0);
66 uint16_t readUInt16(const uint16_t defVal = 0);
67 uint32_t readUInt32(const uint32_t defVal = 0);
68 bool readBool(const bool defVal = false);
69 float readFloat(const float defVal = 0.00);
70 };
71 class ConfigWriter {
72 public:
73 30 virtual ~ConfigWriter() {}
74 virtual bool writeBytes(const uint8_t *buf, size_t len) = 0;
75 bool writeChar(const char val);
76 bool writeString(const char *val, size_t len, const char tok = CFG_VALUE_SEP);
77 bool writeVarString(const char *val, const char tok = CFG_VALUE_SEP);
78 bool writeInt8(const int8_t val, const char tok = CFG_VALUE_SEP);
79 bool writeUInt8(const uint8_t val, const char tok = CFG_VALUE_SEP);
80 bool writeUInt16(const uint16_t val, const char tok = CFG_VALUE_SEP);
81 bool writeUInt32(const uint32_t val, const char tok = CFG_VALUE_SEP);
82 bool writeBool(const bool val, const char tok = CFG_VALUE_SEP);
83 bool writeFloat(const float val, const uint8_t prec, const char tok = CFG_VALUE_SEP);
84 };
85 // Counts what would be written: the size of a record that varies in length.
86 class ConfigCounter : public ConfigWriter {
87 public:
88 uint32_t bytes = 0;
89 47 bool writeBytes(const uint8_t *buf, size_t len) override { (void)buf; bytes += len; return true; }
90 };
91
92 struct room_record_t {
93 uint8_t roomId = 0;
94 char name[CFG_NAME_LEN] = "";
95 int8_t sortOrder = 0;
96 };
97 struct shade_record_t {
98 uint8_t shadeId = 255;
99 bool paired = false;
100 shade_types shadeType = shade_types::roller;
101 uint32_t remoteAddress = 0;
102 char name[CFG_NAME_LEN] = "";
103 tilt_types tiltType = tilt_types::none;
104 radio_proto proto = radio_proto::RTS;
105 uint8_t bitLength = 56;
106 uint32_t upTime = 10000;
107 uint32_t downTime = 10000;
108 uint32_t tiltTime = 7000;
109 uint16_t stepSize = 100;
110 uint32_t linkedRemotes[SOMFY_MAX_LINKED_REMOTES] = {};
111 uint16_t lastRollingCode = 0;
112 uint8_t flags = 0;
113 float myPos = -1;
114 float myTiltPos = -1;
115 float currentPos = 0;
116 float currentTiltPos = 0;
117 bool flipCommands = false;
118 bool flipPosition = false;
119 uint8_t repeats = 1;
120 int8_t sortOrder = 0;
121 uint8_t gpioUp = 0;
122 uint8_t gpioDown = 0;
123 uint8_t gpioMy = 0;
124 uint8_t gpioFlags = 0;
125 uint8_t roomId = 0;
126 };
127 struct group_record_t {
128 uint8_t groupId = 255;
129 group_types groupType = group_types::channel;
130 uint32_t remoteAddress = 0;
131 char name[CFG_NAME_LEN] = "";
132 radio_proto proto = radio_proto::RTS;
133 uint8_t bitLength = 56;
134 // Read without the gaps the file may have.
135 uint8_t linkedShades[SOMFY_MAX_GROUPED_SHADES] = {};
136 uint8_t repeats = 1;
137 int8_t sortOrder = 0;
138 bool flipCommands = false;
139 uint8_t roomId = 0;
140 uint16_t lastRollingCode = 0;
141 // Versions before 23 have none.
142 bool hasRollingCode = false;
143 };
144 struct settings_record_t {
145 // The firmware that wrote the backup. Not restored.
146 char fwVersion[CFG_VERSION_LEN] = "";
147 char hostname[CFG_HOSTNAME_LEN] = "";
148 char ntpServer[CFG_NTP_SERVER_LEN] = "";
149 char posixZone[CFG_POSIX_ZONE_LEN] = "";
150 bool ssdpBroadcast = false;
151 bool checkForUpdate = true;
152 };
153 struct net_record_t {
154 uint8_t connType = 0;
155 bool dhcp = true;
156 char ip[CFG_IP_LEN] = "";
157 char gateway[CFG_IP_LEN] = "";
158 char subnet[CFG_IP_LEN] = "";
159 char dns1[CFG_IP_LEN] = "";
160 char dns2[CFG_IP_LEN] = "";
161 char mqttProtocol[CFG_MQTT_PROTOCOL_LEN] = "";
162 char mqttHostname[CFG_MQTT_HOSTNAME_LEN] = "";
163 uint16_t mqttPort = 1883;
164 bool mqttPubDisco = false;
165 char mqttRootTopic[CFG_MQTT_TOPIC_LEN] = "";
166 char mqttDiscoTopic[CFG_MQTT_TOPIC_LEN] = "";
167 // Only boards with Ethernet write these, and only the board that wrote
168 // them reads them back.
169 uint8_t ethBoardType = 1;
170 uint8_t ethPhyType = 0;
171 uint8_t ethClkMode = 0;
172 int8_t ethPhyAddress = 1;
173 int8_t ethPWRPin = 1;
174 int8_t ethMDCPin = 16;
175 int8_t ethMDIOPin = 23;
176 };
177 struct trans_record_t {
178 bool enabled = false;
179 radio_proto proto = radio_proto::RTS;
180 uint8_t type = 56;
181 uint8_t SCKPin = 18;
182 uint8_t CSNPin = 5;
183 uint8_t MOSIPin = 23;
184 uint8_t MISOPin = 19;
185 uint8_t TXPin = 13;
186 uint8_t RXPin = 35;
187 float frequency = 433.42;
188 float rxBandwidth = 99.97;
189 float deviation = 47.60;
190 int8_t txPower = 10;
191 bool noiseDetection = false;
192 };
193
194 // The readers leave alone what the record's version lacks, so a record that
195 // starts as the shade, group or settings it is read into keeps their values.
196 bool writeConfigHeader(ConfigWriter &w, const config_header_t &header);
197 bool readConfigHeader(ConfigReader &r, config_header_t &header);
198 bool writeRoomRecord(ConfigWriter &w, const room_record_t &rec);
199 bool readRoomRecord(ConfigReader &r, room_record_t &rec);
200 bool writeShadeRecord(ConfigWriter &w, const shade_record_t &rec);
201 bool readShadeRecord(ConfigReader &r, const config_header_t &header, shade_record_t &rec);
202 bool writeGroupRecord(ConfigWriter &w, const group_record_t &rec);
203 bool readGroupRecord(ConfigReader &r, const config_header_t &header, group_record_t &rec);
204 bool writeRepeaterRecord(ConfigWriter &w, const uint32_t (&repeaters)[SOMFY_MAX_REPEATERS]);
205 bool readRepeaterRecord(ConfigReader &r, uint32_t (&repeaters)[SOMFY_MAX_REPEATERS]);
206 bool writeSettingsRecord(ConfigWriter &w, const settings_record_t &rec);
207 bool readSettingsRecord(ConfigReader &r, const config_header_t &header, settings_record_t &rec);
208 // withEthernet: the Ethernet settings, which a board without Ethernet leaves out.
209 bool writeNetRecord(ConfigWriter &w, const net_record_t &rec, bool withEthernet);
210 bool readNetRecord(ConfigReader &r, const config_header_t &header, net_record_t &rec, bool withEthernet);
211 bool writeTransRecord(ConfigWriter &w, const trans_record_t &rec);
212 bool readTransRecord(ConfigReader &r, trans_record_t &rec);
213 // Moves past count records without reading them.
214 bool skipRecords(ConfigReader &r, uint32_t count);
215
216 #endif
217