kopia lustrzana https://github.com/weetmuts/wmbusmeters
Improved support for amber wmbus device.
rodzic
41f4eca30a
commit
3a18f6c59a
|
@ -178,8 +178,8 @@ private:
|
|||
LinkModeSet parseLinkModes(string modes);
|
||||
bool isValidLinkModes(string modes);
|
||||
|
||||
// A wmbus specified device is supplied on the command line or in the config file.
|
||||
// It has this format "alias=file:type(id):fq:bps:linkmods:CMD(command)"
|
||||
// A specified bus device is supplied on the command line or in the config file.
|
||||
// It has this format "alias=file:type[id](extras):fq:bps:linkmods:CMD(command)"
|
||||
struct SpecifiedDevice
|
||||
{
|
||||
std::string bus_alias; // A bus alias, necessary for C2/T2 meters and mbus.
|
||||
|
|
|
@ -129,7 +129,7 @@ struct ConfigAMB8465
|
|||
};
|
||||
|
||||
/*
|
||||
Which receive mode can hear which transmit mode:
|
||||
Which receive mode can hear which transmit mode?
|
||||
|
||||
868 MHz
|
||||
|
||||
|
@ -142,9 +142,9 @@ S2 0x03 --> S2 (0x03)
|
|||
T1-Meter 0x05 (to_collector) --> T2-Other (0x08) or T2/C2-Other (0x09)
|
||||
T1-Other 0x06 (to_meter) --> T2-Meter (0x07)
|
||||
T2-Meter 0x07 (to_collector) --> T2-Other (0x08) or T2/C2-Other (0x09)
|
||||
T2-Other 0x08 (to_collector) --> T2-Meter (0x07)
|
||||
T2-Other 0x08 (to_meter) --> T2-Meter (0x07)
|
||||
|
||||
T2/C2-Other 0x09 (to_collector) --> transmit uses last received mode T2 or C2.
|
||||
T2/C2-Other 0x09 (to_collector) transmit uses last received mode T2 or C2. -->
|
||||
|
||||
R2-Meter 0x0A (to_collector) --> R2-Other (0x0B)
|
||||
R2-Other 0x0B (to_meter) --> R2-Meter (0x0A)
|
||||
|
@ -173,31 +173,129 @@ N2g 0x0D --> N2f (0x0D)
|
|||
|
||||
*/
|
||||
|
||||
uchar setupBusDeviceToReceiveTelegramsFromMeter(LinkModeSet lms)
|
||||
uchar setupBusDeviceToReceiveTelegrams(LinkModeSet lms)
|
||||
{
|
||||
if (lms.has(LinkMode::C1) && lms.has(LinkMode::T1))
|
||||
{
|
||||
// Listening to meter transmissions on C1 and T1.
|
||||
// Using collector receive mode C2/T2-Other (0x09).
|
||||
return 0x09;
|
||||
// Using receive mode C2/T2-Other (0x09).
|
||||
return (int)LinkModeAMB::C2T2Other;
|
||||
}
|
||||
else if (lms.has(LinkMode::C1))
|
||||
if (lms.has(LinkMode::S1) || lms.has(LinkMode::S1m) || lms.has(LinkMode::S2))
|
||||
{
|
||||
// Listening to S1, S1-m.
|
||||
// Using collector receive (and bi-directional) mode S2 (0x03).
|
||||
return (int)LinkModeAMB::S2;
|
||||
}
|
||||
if (lms.has(LinkMode::T1))
|
||||
{
|
||||
// Listening to meter transmissions T1 only.
|
||||
// Using collector receive mode T2-Other (0x08)
|
||||
return (int)LinkModeAMB::T2Other;
|
||||
}
|
||||
if (lms.has(LinkMode::T2))
|
||||
{
|
||||
// Listening to collector transmissions T1 only.
|
||||
// Using meter receive mode T2-Meter (0x07)
|
||||
return (int)LinkModeAMB::T2Meter;
|
||||
}
|
||||
if (lms.has(LinkMode::C1))
|
||||
{
|
||||
// Listening to meter transmissions on C1 only.
|
||||
// Using collector receive mode C2-Other (0x0e)
|
||||
return 0x0E;
|
||||
return (int)LinkModeAMB::C2Other;
|
||||
}
|
||||
else if (lms.has(LinkMode::T1))
|
||||
if (lms.has(LinkMode::C2))
|
||||
{
|
||||
// Listening to meter transmissions T1 only.
|
||||
// Using collector received mode T2-Other (0x08)
|
||||
return 0x08;
|
||||
// Listening to collector transmissions on C1 only.
|
||||
// Using meter receive mode C2-Meter (0x0d)
|
||||
return (int)LinkModeAMB::C2Meter;
|
||||
}
|
||||
else if (lms.has(LinkMode::S1) || lms.has(LinkMode::S1m))
|
||||
if (lms.has(LinkMode::N1a))
|
||||
{
|
||||
// Listening only to S1 and S1-m
|
||||
return 0x03;
|
||||
// Listening to meter transmission N1a.
|
||||
// Using collector receive mode N2a (0x02).
|
||||
return (int)LinkModeAMB::N2a;
|
||||
}
|
||||
if (lms.has(LinkMode::N1b))
|
||||
{
|
||||
// Listening to meter transmission N1b.
|
||||
// Using collector receive mode N2b (0x04).
|
||||
return (int)LinkModeAMB::N2b;
|
||||
}
|
||||
if (lms.has(LinkMode::N1c))
|
||||
{
|
||||
// Listening to meter transmission N1c.
|
||||
// Using collector receive mode N2c (0x06).
|
||||
return (int)LinkModeAMB::N2c;
|
||||
}
|
||||
if (lms.has(LinkMode::N1d))
|
||||
{
|
||||
// Listening to meter transmission N1d.
|
||||
// Using collector receive mode N2d (0x08).
|
||||
return (int)LinkModeAMB::N2d;
|
||||
}
|
||||
if (lms.has(LinkMode::N1e))
|
||||
{
|
||||
// Listening to meter transmission N1e.
|
||||
// Using collector receive mode N2e (0x0a).
|
||||
return (int)LinkModeAMB::N2e;
|
||||
}
|
||||
if (lms.has(LinkMode::N1f))
|
||||
{
|
||||
// Listening to meter transmission N1f.
|
||||
// Using collector receive mode N2f (0x0c).
|
||||
return (int)LinkModeAMB::N2f;
|
||||
}
|
||||
|
||||
// Error
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
uchar setupBusDeviceToSendTelegram(LinkMode lm)
|
||||
{
|
||||
if (lm == LinkMode::S1)
|
||||
{
|
||||
// Send S1 telegram using mode S1 (0x01).
|
||||
return (int)LinkModeAMB::S1;
|
||||
}
|
||||
if (lm == LinkMode::S1m)
|
||||
{
|
||||
// Send S1 telegram using mode S1m (0x02).
|
||||
return (int)LinkModeAMB::S1m;
|
||||
}
|
||||
if (lm == LinkMode::S2)
|
||||
{
|
||||
// Bi-directional communication with meter using mode S2 (0x03).
|
||||
return (int)LinkModeAMB::S2;
|
||||
}
|
||||
if (lm == LinkMode::T1)
|
||||
{
|
||||
// Send T1 telegram using mode T1-Meter (0x05).
|
||||
return (int)LinkModeAMB::T1Meter;
|
||||
}
|
||||
if (lm == LinkMode::T2)
|
||||
{
|
||||
// Send T2 telegram to meter using mode T2-Other (0x06).
|
||||
return (int)LinkModeAMB::T2Other;
|
||||
}
|
||||
if (lm == LinkMode::C1)
|
||||
{
|
||||
// Send C1 telegram using mode C1-Meter (0x0c).
|
||||
return (int)LinkModeAMB::C1Meter;
|
||||
}
|
||||
if (lm == LinkMode::C2)
|
||||
{
|
||||
// Send C2 telegram to meter using mode C2-Other (0x0e).
|
||||
return (int)LinkModeAMB::C2Other;
|
||||
}
|
||||
|
||||
if (lm == LinkMode::N1a) return (int)LinkModeAMB::N1a;
|
||||
if (lm == LinkMode::N1b) return (int)LinkModeAMB::N1b;
|
||||
if (lm == LinkMode::N1c) return (int)LinkModeAMB::N1c;
|
||||
if (lm == LinkMode::N1d) return (int)LinkModeAMB::N1d;
|
||||
if (lm == LinkMode::N1e) return (int)LinkModeAMB::N1e;
|
||||
if (lm == LinkMode::N1f) return (int)LinkModeAMB::N1f;
|
||||
|
||||
// Error
|
||||
return 0xff;
|
||||
|
@ -215,9 +313,11 @@ struct WMBusAmber : public virtual BusDeviceCommonImplementation
|
|||
{
|
||||
return
|
||||
C1_bit |
|
||||
C2_bit |
|
||||
S1_bit |
|
||||
S1m_bit |
|
||||
T1_bit;
|
||||
T1_bit |
|
||||
T2_bit;
|
||||
}
|
||||
int numConcurrentLinkModes() { return 1; }
|
||||
bool canSetLinkModes(LinkModeSet desired_modes)
|
||||
|
@ -253,6 +353,7 @@ private:
|
|||
vector<uchar> response_;
|
||||
|
||||
LinkModeSet link_modes_ {};
|
||||
uchar last_set_link_mode_ { 0x01 };
|
||||
bool rssi_expected_ {};
|
||||
struct timeval timestamp_last_rx_ {};
|
||||
|
||||
|
@ -418,11 +519,11 @@ bool WMBusAmber::deviceSetLinkModes(LinkModeSet lms)
|
|||
|
||||
LOCK_WMBUS_EXECUTING_COMMAND(devicesSetLinkModes);
|
||||
|
||||
request_.resize(8);
|
||||
request_.resize(5);
|
||||
request_[0] = AMBER_SERIAL_SOF;
|
||||
request_[1] = CMD_SET_MODE_REQ;
|
||||
request_[2] = 1; // Len
|
||||
request_[3] = setupBusDeviceToReceiveTelegramsFromMeter(lms);
|
||||
request_[3] = setupBusDeviceToReceiveTelegrams(lms);
|
||||
request_[4] = xorChecksum(request_, 0, 4);
|
||||
|
||||
verbose("(amb8465) set link mode %02x\n", request_[3]);
|
||||
|
@ -443,6 +544,8 @@ bool WMBusAmber::deviceSetLinkModes(LinkModeSet lms)
|
|||
}
|
||||
|
||||
link_modes_ = lms;
|
||||
last_set_link_mode_ = request_[3];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -687,6 +790,50 @@ bool WMBusAmber::sendTelegram(LinkMode lm, TelegramFormat format, vector<uchar>
|
|||
|
||||
bool rc = false;
|
||||
|
||||
if (serial()->readonly()) return true; // Feeding from stdin or file.
|
||||
|
||||
uchar link_mode = setupBusDeviceToSendTelegram(lm);
|
||||
|
||||
if (link_mode == 0xff)
|
||||
{
|
||||
error("(amb8465) setting link mode %s for sending is not supported for amb8465 \n", toString(lm));
|
||||
}
|
||||
|
||||
{
|
||||
// Empty the read buffer we do not want any partial data lying around
|
||||
// because we expect a response to arrive.
|
||||
LOCK_WMBUS_RECEIVING_BUFFER(deviceSetLinkMode_ClearBuffer);
|
||||
read_buffer_.clear();
|
||||
}
|
||||
|
||||
if (link_mode != last_set_link_mode_)
|
||||
{
|
||||
// Switch to the send link mode.
|
||||
request_.resize(5);
|
||||
request_[0] = AMBER_SERIAL_SOF;
|
||||
request_[1] = CMD_SET_MODE_REQ;
|
||||
request_[2] = 1; // Len
|
||||
request_[3] = link_mode;
|
||||
request_[4] = xorChecksum(request_, 0, 4);
|
||||
|
||||
verbose("(amb8465) set link mode %02x for sending\n", request_[3]);
|
||||
bool sent = serial()->send(request_);
|
||||
|
||||
if (sent)
|
||||
{
|
||||
bool ok = waitForResponse(CMD_SET_MODE_REQ | 0x80);
|
||||
if (ok)
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
warning("Warning! Did not get confirmation on set link mode for amb8465 for sending\n");
|
||||
rc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request_.resize(content.size()+4);
|
||||
request_[0] = AMBER_SERIAL_SOF;
|
||||
request_[1] = CMD_DATA_REQ;
|
||||
|
@ -714,6 +861,34 @@ bool WMBusAmber::sendTelegram(LinkMode lm, TelegramFormat format, vector<uchar>
|
|||
}
|
||||
}
|
||||
|
||||
if (link_mode != last_set_link_mode_)
|
||||
{
|
||||
// Restore the link mode.
|
||||
request_.resize(5);
|
||||
request_[0] = AMBER_SERIAL_SOF;
|
||||
request_[1] = CMD_SET_MODE_REQ;
|
||||
request_[2] = 1; // Len
|
||||
request_[3] = last_set_link_mode_;
|
||||
request_[4] = xorChecksum(request_, 0, 4);
|
||||
|
||||
verbose("(amb8465) set link mode %02x for restore after sending\n", request_[3]);
|
||||
bool sent = serial()->send(request_);
|
||||
|
||||
if (sent)
|
||||
{
|
||||
bool ok = waitForResponse(CMD_SET_MODE_REQ | 0x80);
|
||||
if (ok)
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
warning("Warning! Did not get confirmation on set link mode for amb8465 for restore after sending\n");
|
||||
rc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2019 Fredrik Öhrström (CC0-1.0)
|
||||
// Copyright (C) 2019-2022 Fredrik Öhrström (CC0-1.0)
|
||||
// Defines documented in the Manual for the AMBER wM-Bus Modules Version 2.7
|
||||
|
||||
#define AMBER_SERIAL_SOF 0xFF
|
||||
|
@ -21,3 +21,43 @@
|
|||
#define CMD_SET_AES_KEY_REQ 0x50
|
||||
#define CMD_CLR_AES_KEY_REQ 0x51
|
||||
#define CMD_GET_AES_DEV_REQ 0x52
|
||||
|
||||
// Both 8465 868MHz and 8336 169Mhz link modes.
|
||||
#define LIST_OF_AMBER_8465_8336_LINK_MODES \
|
||||
X(USER_SELECTED,0x00,txrx,All parameters user selected.) \
|
||||
X(S1,0x01,tx,Meter transmit once per day long preamble.) \
|
||||
X(S1m,0x02,tx,Meter transmit once per day short preamble.) \
|
||||
X(S2,0x03,txrx,Collector receive mode for S1 and S1-m. Might need tuning of preamble.) \
|
||||
X(Reserved,0x04,reserved,) \
|
||||
X(T1Meter,0x05,tx,Meter transmits often.) \
|
||||
X(T1Other,0x06,tx,Collector transmits to meter.) \
|
||||
X(T2Meter,0x07,txrx,Meter bi-directional setting.) \
|
||||
X(T2Other,0x08,txrx,Collector bi-directional setting.) \
|
||||
X(C2T2Other,0x09,txrx,Collector receive C/T send using latest received type.) \
|
||||
X(R2Meter,0x0a,txrx,Meter bi-directional.) \
|
||||
X(R2Other,0x0b,txrx,Collector bi-directional.) \
|
||||
X(C1Meter,0x0c,tx,Meter transmits often more energy efficient that T.) \
|
||||
X(C2Meter,0x0d,txrx,Meter bi-directional setting.) \
|
||||
X(C2Other,0x0e,txrx,Collector bi-directional setting.) \
|
||||
X(PinSelect,0x0f,pinselect,) \
|
||||
X(N1a,0x01,txrx,) \
|
||||
X(N2a,0x02,txrx,) \
|
||||
X(N1b,0x03,txrx,) \
|
||||
X(N2b,0x04,txrx,) \
|
||||
X(N1c,0x05,txrx,) \
|
||||
X(N2c,0x06,txrx,) \
|
||||
X(N1d,0x07,txrx,) \
|
||||
X(N2d,0x08,txrx,) \
|
||||
X(N1e,0x09,txrx,) \
|
||||
X(N2e,0x0a,txrx,) \
|
||||
X(N1f,0x0b,txrx,) \
|
||||
X(N2f,0x0c,txrx,) \
|
||||
X(UNKNOWN,0xff,unknown,)
|
||||
|
||||
enum class LinkModeAMB {
|
||||
#define X(name,num,sendrcv,info) name = num,
|
||||
LIST_OF_AMBER_8465_8336_LINK_MODES
|
||||
#undef X
|
||||
};
|
||||
|
||||
string toString(LinkModeAMB lm);
|
||||
|
|
|
@ -160,19 +160,6 @@ LIST_OF_IM871A_LINK_MODES
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Which receive mode can hear which transmit mode:
|
||||
|
||||
868 MHz
|
||||
|
||||
Transmit Receive
|
||||
------------------------------------------------------------------------
|
||||
|
||||
S1 (to_collector) -->
|
||||
|
||||
*/
|
||||
|
||||
struct WMBusIM871aIM170A : public virtual BusDeviceCommonImplementation
|
||||
{
|
||||
bool ping();
|
||||
|
@ -188,9 +175,11 @@ struct WMBusIM871aIM170A : public virtual BusDeviceCommonImplementation
|
|||
{
|
||||
return
|
||||
C1_bit |
|
||||
C2_bit |
|
||||
S1_bit |
|
||||
S1m_bit |
|
||||
T1_bit;
|
||||
T1_bit |
|
||||
T2_bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -567,12 +556,16 @@ bool WMBusIM871aIM170A::deviceSetLinkModes(LinkModeSet lms)
|
|||
request_[6] = (int)LinkModeIM871A::CT_N1A;
|
||||
} else if (lms.has(LinkMode::C1)) {
|
||||
request_[6] = (int)LinkModeIM871A::C1a;
|
||||
} else if (lms.has(LinkMode::C2)) {
|
||||
request_[6] = (int)LinkModeIM871A::C2b;
|
||||
} else if (lms.has(LinkMode::S1)) {
|
||||
request_[6] = (int)LinkModeIM871A::S1;
|
||||
} else if (lms.has(LinkMode::S1m)) {
|
||||
request_[6] = (int)LinkModeIM871A::S1m;
|
||||
} else if (lms.has(LinkMode::T1)) {
|
||||
request_[6] = (int)LinkModeIM871A::T1;
|
||||
} else if (lms.has(LinkMode::T2)) {
|
||||
request_[6] = (int)LinkModeIM871A::T2;
|
||||
} else if (lms.has(LinkMode::N1a)) {
|
||||
request_[6] = (int)LinkModeIM871A::CT_N1A;
|
||||
} else if (lms.has(LinkMode::N1b)) {
|
||||
|
|
Ładowanie…
Reference in New Issue