ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
lonworks.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file lonworks.cpp
6 * @brief LonWorks / LON-IP network-variable codec (see lonworks.h).
7 */
8
10
11#if PC_ENABLE_LONWORKS
12
13#include <string.h>
14
15size_t pc_lon_build_nv(uint8_t msg_code, uint16_t selector, const uint8_t *value, size_t value_len, uint8_t *out,
16 size_t cap)
17{
18 if (!out || (value_len && !value) || selector > Lon::LON_NV_SELECTOR_MAX)
19 {
20 return 0;
21 }
22 size_t n = 3 + value_len;
23 if (n > cap)
24 {
25 return 0;
26 }
27 out[0] = msg_code;
28 out[1] = (uint8_t)(selector >> 8); // 14-bit selector, big-endian
29 out[2] = (uint8_t)selector;
30 if (value_len)
31 {
32 memcpy(out + 3, value, value_len);
33 }
34 return n;
35}
36
37bool pc_lon_parse_nv(const uint8_t *pdu, size_t len, LonNv *out)
38{
39 if (!pdu || !out || len < 3)
40 {
41 return false;
42 }
43 out->msg_code = pdu[0];
44 out->selector = (uint16_t)(((pdu[1] & 0x3F) << 8) | pdu[2]); // 14-bit
45 out->value = (len > 3) ? (pdu + 3) : nullptr;
46 out->value_len = len - 3;
47 return true;
48}
49
50void pc_lon_snvt_temp_encode(double celsius, uint8_t out[2])
51{
52 // SNVT_temp: kelvin in 0.01 K steps -> (celsius + 273.15) * 100, as a signed 16-bit big-endian.
53 double kelvin_hundredths = (celsius + 273.15) * 100.0;
54 int32_t v = (int32_t)(kelvin_hundredths >= 0 ? kelvin_hundredths + 0.5 : kelvin_hundredths - 0.5);
55 if (v > 32767)
56 {
57 v = 32767;
58 }
59 if (v < -32768)
60 {
61 v = -32768;
62 }
63 uint16_t u = (uint16_t)v;
64 out[0] = (uint8_t)(u >> 8);
65 out[1] = (uint8_t)u;
66}
67
68double pc_lon_snvt_temp_decode(const uint8_t in[2])
69{
70 int16_t v = (int16_t)((in[0] << 8) | in[1]);
71 return (double)v / 100.0 - 273.15;
72}
73
74void pc_lon_snvt_switch_encode(double percent, uint8_t state, uint8_t out[2])
75{
76 // SNVT_switch: value is 0..200 in 0.5% steps (0..100.5%), state is 0/1/0xFF.
77 if (percent < 0)
78 {
79 percent = 0;
80 }
81 if (percent > 100.5)
82 {
83 percent = 100.5;
84 }
85 uint8_t v = (uint8_t)(percent * 2.0 + 0.5);
86 out[0] = v;
87 out[1] = state;
88}
89
90void pc_lon_snvt_switch_decode(const uint8_t in[2], double *percent, uint8_t *state)
91{
92 if (percent)
93 {
94 *percent = (double)in[0] / 2.0;
95 }
96 if (state)
97 {
98 *state = in[1];
99 }
100}
101
102#endif // PC_ENABLE_LONWORKS
LonWorks / LON-IP (ISO/IEC 14908) network-variable codec (PC_ENABLE_LONWORKS).