Skip to content

Commit 5df0017

Browse files
committed
inclusive language
1 parent 9306227 commit 5df0017

File tree

5 files changed

+251
-234
lines changed

5 files changed

+251
-234
lines changed

README.md

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Arduino Dutch Smart meter (DSMR) parser
2-
=======================================
1+
# Arduino Dutch Smart meter (DSMR) parser
2+
33
This is an Arduino library for interfacing with Dutch smart meters, through
44
their P1 port. This library can take care of controlling the "request" pin,
55
reading messages and parsing them.
@@ -11,8 +11,8 @@ should be possible to adapt for use outside of the Arduino environment.
1111
When using Arduino, version 1.6.6 or above is required because this
1212
library needs C++11 support which was enabled in that version.
1313

14-
Protocol
15-
--------
14+
## Protocol
15+
1616
Every smart meter in the Netherlands has to comply with the Dutch Smart
1717
Meter Requirements (DSMR). At the time of writing, DSMR 4.x is the
1818
current version. The DSMR 5.0 P1 specification is available and expected to
@@ -59,11 +59,11 @@ used.
5959

6060
A typical P1 message looks something like this:
6161

62-
/KFM5KAIFA-METER
62+
/KFM5KAIFA-METER
6363

64-
1-0:1.8.1(000671.578*kWh)
65-
1-0:1.7.0(00.318*kW)
66-
!1E1D
64+
1-0:1.8.1(000671.578*kWh)
65+
1-0:1.7.0(00.318*kW)
66+
!1E1D
6767

6868
This includes an identification header at the top, a checksum at the
6969
bottom, and one or more lines of data in the middle. This example is
@@ -72,25 +72,25 @@ really stripped down, real messages will have more data in them.
7272
The first part of the line (e.g. `1-0:1.8.1`) is the (OBIS) id of the
7373
field, which defines the meaning and format of the rest of the line.
7474

75-
Parsing a message
76-
-----------------
75+
## Parsing a message
76+
7777
Unlike other solutions floating around (which typically do some pattern
7878
matching to extract the data they need), this code properly parses
7979
messages, verifying the checksum and really parses each line according
8080
to the specifications. This should make for more reliable parsing, and
8181
allows for useful parser error messages:
8282

83-
1-0:1.8.1(000671.578*XWh)
84-
^
85-
Error: Invalid unit
83+
1-0:1.8.1(000671.578*XWh)
84+
^
85+
Error: Invalid unit
8686

87-
1-0:1.8.1(0006#71.578*kWh)
88-
^
89-
Error: Invalid number
87+
1-0:1.8.1(0006#71.578*kWh)
88+
^
89+
Error: Invalid number
9090

91-
!6F4A
92-
^
93-
Checksum mismatch
91+
!6F4A
92+
^
93+
Checksum mismatch
9494

9595
This library uses C++ templates extensively. This allows defining a
9696
custom datatype by listing the fields you are interested in, and then
@@ -102,42 +102,42 @@ is parsed and stored into the corresponding field.
102102
As an example, consider we want to parse the identification and current
103103
power fields in the example message above. We define a datatype:
104104

105-
using MyData = ParsedData<
106-
/* String */ identification,
107-
/* FixedValue */ power_delivered
108-
>;
105+
using MyData = ParsedData<
106+
/* String */ identification,
107+
/* FixedValue */ power_delivered
108+
>;
109109

110110
The syntax is a bit weird because of the template magic used, but the
111111
above essentially defines a struct with members for each field to be
112112
parsed. For each field, there is also an associated `xxx_present`
113113
member, which can be used to check whether the field was present in the
114114
parsed data (if it is false, the associated field contains uninitialized
115-
data). There is some extra stuff in the background, but the `MyData`
115+
data). There is some extra stuff in the background, but the `MyData`
116116
can be used just like the below struct. It also takes up the same amount
117117
of space.
118118

119-
struct MyData {
120-
bool identification_present;
121-
String identification;
122-
bool power_delivered_present;
123-
FixedValue power_delivered;
124-
};
119+
struct MyData {
120+
bool identification_present;
121+
String identification;
122+
bool power_delivered_present;
123+
FixedValue power_delivered;
124+
};
125125

126126
After this, call the parser. By passing our custom datatype defined
127127
above, the parser knows what fields to look for.
128128

129-
MyData data;
130-
ParseResult<void> res = P1Parser::parse(&data, msg, lengthof(msg));
129+
MyData data;
130+
ParseResult<void> res = P1Parser::parse(&data, msg, lengthof(msg));
131131

132132
Finally, we can check if the parsing was succesful and access the parsed
133133
values as members of `data`:
134134

135-
if (!res.err && res.all_present()) {
136-
// Succesfully parsed, print results:
137-
Serial.println(data.identification);
138-
Serial.print(data.power_delivered.int_val());
139-
Serial.println("W");
140-
}
135+
if (!res.err && res.all_present()) {
136+
// Succesfully parsed, print results:
137+
Serial.println(data.identification);
138+
Serial.print(data.power_delivered.int_val());
139+
Serial.println("W");
140+
}
141141

142142
In this case, we check whether parsing was successful, but also check
143143
that all defined fields were present in the parsed message (using the
@@ -156,8 +156,8 @@ fields, even if they are not present in the output you want to parse. It
156156
is recommended to limit the list of fields to just the ones that you
157157
need, to make the parsing and printing code smaller and faster.
158158

159-
Parsed value types
160-
------------------
159+
## Parsed value types
160+
161161
Some values are parsed to an Arduino `String` value or C++ integer type,
162162
those should be fairly straightforward. There are three special types
163163
that need some explanation: `FixedValue` and `TimestampedFixedValue`.
@@ -186,10 +186,10 @@ If you access the field directly, it will automatically be converted to
186186
version is sufficient, you can call the `int_val()` method to get the
187187
integer version returned.
188188

189-
// Print as float, in kW
190-
Serial.print(data.power_delivered);
191-
// Print as integer, in W
192-
Serial.print(data.power_delivered.int_val());
189+
// Print as float, in kW
190+
Serial.print(data.power_delivered);
191+
// Print as integer, in W
192+
Serial.print(data.power_delivered.int_val());
193193

194194
Additionally there is a `TimestampedFixedValue` method, which works
195195
identically, but additionally has a `timestamp()` method which returns
@@ -201,16 +201,17 @@ Parsing these into something like a UNIX timestamp is tricky (think
201201
leap years and seconds) and of limited use, so this just keeps the
202202
original format.
203203

204-
Connecting the P1 port
205-
----------------------
204+
## Connecting the P1 port
205+
206206
The P1 port essentially consists of three parts:
207-
- A 5V power supply (this was not present in 3.x).
208-
- A serial TX pin. This sends meter data using 0/5V signalling, using
209-
idle low. Note that this is the voltage level commonly referred to as
210-
"TTL serial", but the polarity is reversed (more like RS232). This
211-
port uses 115200 bps 8N1 (3.x and before used 9600 bps).
212-
- A request pin - 5V needs to be applied to this pin to start
213-
generating output on the TX pin.
207+
208+
- A 5V power supply (this was not present in 3.x).
209+
- A serial TX pin. This sends meter data using 0/5V signalling, using
210+
idle low. Note that this is the voltage level commonly referred to as
211+
"TTL serial", but the polarity is reversed (more like RS232). This
212+
port uses 115200 bps 8N1 (3.x and before used 9600 bps).
213+
- A request pin - 5V needs to be applied to this pin to start
214+
generating output on the TX pin.
214215

215216
To connect to an Arduino that has an unused hardware serial port (like
216217
an Arduino Mega, Leonardo or Micro), the signal has to inverted. This
@@ -222,24 +223,24 @@ inverting, in software using Arduino's SoftwareSerial library. However,
222223
it seems there are still occasional reception errors when using
223224
SoftwareSerial.
224225

225-
Slave meters
226-
------------
226+
## Sub meters
227+
227228
In addition to a smart electricity meter, there can be additional
228-
slave meters attached (e.g., gas, water, thermal and slave electricity
229+
sub meters attached (e.g., gas, water, thermal and sub electricity
229230
meter). These can talk to the main meter using the (wired or wireless)
230231
MBUS protocol to regularly (hourly for 4.x, every 5 minutes for 5.0)
231232
send over their meter readings. Based on the configuration / connection,
232-
each of these slaves gets an MBUS identifier (1-4).
233+
each of these subs gets an MBUS identifier (1-4).
233234

234235
In the P1 message, this identifier is used as the second number in the
235-
OBIS identifiers for the fields for the slave. Currently, the code has
236+
OBIS identifiers for the fields for the sub. Currently, the code has
236237
the assignment from MBUS identifier to device type hardcoded in
237238
`fields.h`. For the most common configuration of an electricity meter with
238-
a single gas meter as slave, this works straight away. Other
239+
a single gas meter as sub, this works straight away. Other
239240
configurations might need changes to `fields.h` to work.
240241

241-
License
242-
-------
242+
## License
243+
243244
All of the code and documentation in this library is licensed under the
244245
MIT license, with the exception of the examples, which are licensed
245246
under an even more liberal license.

0 commit comments

Comments
 (0)