refactor: mqtt data model.

This commit is contained in:
2026-05-09 15:19:15 +08:00
parent 85f28b5660
commit cb7ed2c4cc
4 changed files with 1003 additions and 449 deletions
+57 -30
View File
@@ -4,40 +4,62 @@ import "gorm.io/gorm"
type MqttHeartRateRecord struct { type MqttHeartRateRecord struct {
gorm.Model gorm.Model
Identifier string `gorm:"uniqueIndex;size:255" json:"identifier"` Identifier string `gorm:"uniqueIndex;size:255" json:"identifier"`
Topic string `gorm:"size:255;index" json:"topic"` Topic string `gorm:"size:255;index" json:"topic"`
RegionID uint32 `gorm:"index" json:"regionId"` RegionID uint32 `gorm:"index" json:"regionId"`
GatewayMAC string `gorm:"size:32;index" json:"gatewayMac"` GatewayMAC string `gorm:"size:32;index" json:"gatewayMac"`
BandID uint32 `gorm:"index" json:"bandId"` GatewaySchemaVersion uint32 `json:"gatewaySchemaVersion"`
BeltAddr string `gorm:"size:64;index" json:"beltAddr"` GatewayActiveUplink int32 `gorm:"type:int" json:"gatewayActiveUplink"`
PacketNum uint32 `gorm:"index" json:"packetNum"` GatewayCellularIMEI string `gorm:"size:64" json:"gatewayCellularImei"`
HeartRate int `gorm:"type:int" json:"heartRate"` GatewayCellularRSSI int32 `gorm:"type:int" json:"gatewayCellularRssi"`
HrConfidence int `gorm:"type:int" json:"hrConfidence"` GatewayCellularBER int32 `gorm:"type:int" json:"gatewayCellularBer"`
IsActive bool `json:"isActive"` BandID uint32 `gorm:"index" json:"bandId"`
IsOnSkin bool `json:"isOnSkin"` BeltAddr string `gorm:"size:64;index" json:"beltAddr"`
Battery uint32 `json:"battery"` PacketNum uint32 `gorm:"index" json:"packetNum"`
SignalRSSINeg float64 `gorm:"type:double precision" json:"signalRssiNeg"` HeartRate int `gorm:"type:int" json:"heartRate"`
SNR float64 `gorm:"type:double precision" json:"snr"` HrConfidence int `gorm:"type:int" json:"hrConfidence"`
HubBusID uint32 `json:"hubBusId"` IsActive bool `json:"isActive"`
HubSubDevID uint32 `json:"hubSubDevId"` IsOnSkin bool `json:"isOnSkin"`
ReceivedAt int64 `gorm:"type:bigint;index" json:"receivedAt"` Battery uint32 `json:"battery"`
PacketStatusSource string `gorm:"size:16" json:"packetStatusSource"`
SignalRSSINeg float64 `gorm:"type:double precision" json:"signalRssiNeg"`
SNR float64 `gorm:"type:double precision" json:"snr"`
RawSignalRSSIX2Neg uint32 `json:"rawSignalRssiX2Neg"`
RawSnrPktX4 int32 `gorm:"type:int" json:"rawSnrPktX4"`
HubBusID uint32 `json:"hubBusId"`
HubSubDevID uint32 `json:"hubSubDevId"`
HubRadioBW int32 `gorm:"type:int" json:"hubRadioBw"`
HubRadioSF uint32 `json:"hubRadioSf"`
HubRadioFrequencyMHz float64 `gorm:"type:double precision" json:"hubRadioFrequencyMHz"`
ReceivedAt int64 `gorm:"type:bigint;index" json:"receivedAt"`
} }
type MqttStepCountRecord struct { type MqttStepCountRecord struct {
gorm.Model gorm.Model
Identifier string `gorm:"uniqueIndex;size:255" json:"identifier"` Identifier string `gorm:"uniqueIndex;size:255" json:"identifier"`
Topic string `gorm:"size:255;index" json:"topic"` Topic string `gorm:"size:255;index" json:"topic"`
RegionID uint32 `gorm:"index" json:"regionId"` RegionID uint32 `gorm:"index" json:"regionId"`
GatewayMAC string `gorm:"size:32;index" json:"gatewayMac"` GatewayMAC string `gorm:"size:32;index" json:"gatewayMac"`
BandID uint32 `gorm:"index" json:"bandId"` GatewaySchemaVersion uint32 `json:"gatewaySchemaVersion"`
BeltAddr string `gorm:"size:64;index" json:"beltAddr"` GatewayActiveUplink int32 `gorm:"type:int" json:"gatewayActiveUplink"`
PacketNum uint32 `gorm:"index" json:"packetNum"` GatewayCellularIMEI string `gorm:"size:64" json:"gatewayCellularImei"`
StepCount uint32 `json:"stepCount"` GatewayCellularRSSI int32 `gorm:"type:int" json:"gatewayCellularRssi"`
SignalRSSINeg float64 `gorm:"type:double precision" json:"signalRssiNeg"` GatewayCellularBER int32 `gorm:"type:int" json:"gatewayCellularBer"`
SNR float64 `gorm:"type:double precision" json:"snr"` BandID uint32 `gorm:"index" json:"bandId"`
HubBusID uint32 `json:"hubBusId"` BeltAddr string `gorm:"size:64;index" json:"beltAddr"`
HubSubDevID uint32 `json:"hubSubDevId"` PacketNum uint32 `gorm:"index" json:"packetNum"`
ReceivedAt int64 `gorm:"type:bigint;index" json:"receivedAt"` StepCount uint32 `json:"stepCount"`
PacketStatusSource string `gorm:"size:16" json:"packetStatusSource"`
SignalRSSINeg float64 `gorm:"type:double precision" json:"signalRssiNeg"`
SNR float64 `gorm:"type:double precision" json:"snr"`
RawSignalRSSIX2Neg uint32 `json:"rawSignalRssiX2Neg"`
RawSnrPktX4 int32 `gorm:"type:int" json:"rawSnrPktX4"`
HubBusID uint32 `json:"hubBusId"`
HubSubDevID uint32 `json:"hubSubDevId"`
HubRadioBW int32 `gorm:"type:int" json:"hubRadioBw"`
HubRadioSF uint32 `json:"hubRadioSf"`
HubRadioFrequencyMHz float64 `gorm:"type:double precision" json:"hubRadioFrequencyMHz"`
ReceivedAt int64 `gorm:"type:bigint;index" json:"receivedAt"`
} }
type MqttGatewayStatusRecord struct { type MqttGatewayStatusRecord struct {
@@ -46,6 +68,11 @@ type MqttGatewayStatusRecord struct {
Topic string `gorm:"size:255;index" json:"topic"` Topic string `gorm:"size:255;index" json:"topic"`
RegionID uint32 `gorm:"index" json:"regionId"` RegionID uint32 `gorm:"index" json:"regionId"`
GatewayMAC string `gorm:"size:32;index" json:"gatewayMac"` GatewayMAC string `gorm:"size:32;index" json:"gatewayMac"`
GatewaySchemaVersion uint32 `json:"gatewaySchemaVersion"`
GatewayActiveUplink int32 `gorm:"type:int" json:"gatewayActiveUplink"`
GatewayCellularIMEI string `gorm:"size:64" json:"gatewayCellularImei"`
GatewayCellularRSSI int32 `gorm:"type:int" json:"gatewayCellularRssi"`
GatewayCellularBER int32 `gorm:"type:int" json:"gatewayCellularBer"`
BootCount uint32 `json:"bootCount"` BootCount uint32 `json:"bootCount"`
UptimeMs uint32 `json:"uptimeMs"` UptimeMs uint32 `json:"uptimeMs"`
DurationMsSinceLastPacket uint32 `json:"durationMsSinceLastPacket"` DurationMsSinceLastPacket uint32 `json:"durationMsSinceLastPacket"`
+93 -43
View File
@@ -23,6 +23,14 @@ const (
defaultWorkers = 4 defaultWorkers = 4
) )
type packetStatusSnapshot struct {
source string
signalRSSINeg float64
snr float64
rawSignalRSSIX2Neg uint32
rawSnrPktX4 int32
}
type Listener struct { type Listener struct {
db *gorm.DB db *gorm.DB
cfg config.MQTTConfig cfg config.MQTTConfig
@@ -245,75 +253,107 @@ func (l *Listener) persistTrainingSession(record *models.MqttTrainingSessionReco
} }
func buildHeartRateRecord(measurement *whgw_hrpb.HrMeasurement, topic string, now int64) models.MqttHeartRateRecord { func buildHeartRateRecord(measurement *whgw_hrpb.HrMeasurement, topic string, now int64) models.MqttHeartRateRecord {
regionID := measurement.GetGatewayInfo().GetRegionId() gatewayInfo := measurement.GetGatewayInfo()
hubInfo := measurement.GetHubInfo()
regionID := gatewayInfo.GetRegionId()
if regionID == 0 { if regionID == 0 {
regionID = parseRegionFromTopic(topic) regionID = parseRegionFromTopic(topic)
} }
gatewayMAC := formatMAC(measurement.GetGatewayInfo().GetGatewayMac()) gatewayMAC := formatMAC(gatewayInfo.GetGatewayMac())
packet := measurement.GetHrPacket() packet := measurement.GetHrPacket()
rssi, snr := parsePacketStatus(measurement.GetPacketStatus()) status := parsePacketStatus(measurement.GetPacketStatus())
beltAddr := fmt.Sprintf("%d-%d", regionID, packet.GetId()) beltAddr := fmt.Sprintf("%d-%d", regionID, packet.GetId())
return models.MqttHeartRateRecord{ return models.MqttHeartRateRecord{
Identifier: fmt.Sprintf("hr:%d:%s:%d:%d", regionID, gatewayMAC, packet.GetId(), packet.GetPacketNum()), Identifier: fmt.Sprintf("hr:%d:%s:%d:%d", regionID, gatewayMAC, packet.GetId(), packet.GetPacketNum()),
Topic: topic, Topic: topic,
RegionID: regionID, RegionID: regionID,
GatewayMAC: gatewayMAC, GatewayMAC: gatewayMAC,
BandID: packet.GetId(), GatewaySchemaVersion: gatewayInfo.GetExtra().GetSchemaVersion(),
BeltAddr: beltAddr, GatewayActiveUplink: int32(gatewayInfo.GetExtra().GetActiveUplink().Number()),
PacketNum: packet.GetPacketNum(), GatewayCellularIMEI: gatewayInfo.GetExtra().GetCellularModem().GetImei(),
HeartRate: int(packet.GetHr()), GatewayCellularRSSI: gatewayInfo.GetExtra().GetCellularModem().GetRssi(),
HrConfidence: int(packet.GetStatus().GetHrConfidence().Number()), GatewayCellularBER: gatewayInfo.GetExtra().GetCellularModem().GetBer(),
IsActive: packet.GetStatus().GetIsActive(), BandID: packet.GetId(),
IsOnSkin: packet.GetStatus().GetIsOnSkin(), BeltAddr: beltAddr,
Battery: packet.GetStatus().GetBattery(), PacketNum: packet.GetPacketNum(),
SignalRSSINeg: rssi, HeartRate: int(packet.GetHr()),
SNR: snr, HrConfidence: int(packet.GetStatus().GetHrConfidence().Number()),
HubBusID: measurement.GetHubInfo().GetBusId(), IsActive: packet.GetStatus().GetIsActive(),
HubSubDevID: measurement.GetHubInfo().GetSubDevId(), IsOnSkin: packet.GetStatus().GetIsOnSkin(),
ReceivedAt: now, Battery: packet.GetStatus().GetBattery(),
PacketStatusSource: status.source,
SignalRSSINeg: status.signalRSSINeg,
SNR: status.snr,
RawSignalRSSIX2Neg: status.rawSignalRSSIX2Neg,
RawSnrPktX4: status.rawSnrPktX4,
HubBusID: hubInfo.GetBusId(),
HubSubDevID: hubInfo.GetSubDevId(),
HubRadioBW: int32(hubInfo.GetRadioParameters().GetBw().Number()),
HubRadioSF: hubInfo.GetRadioParameters().GetSf(),
HubRadioFrequencyMHz: float64(hubInfo.GetRadioParameters().GetFrequencyMhz()),
ReceivedAt: now,
} }
} }
func buildStepCountRecord(measurement *whgw_hrpb.StepCountMeasurement, topic string, now int64) models.MqttStepCountRecord { func buildStepCountRecord(measurement *whgw_hrpb.StepCountMeasurement, topic string, now int64) models.MqttStepCountRecord {
regionID := measurement.GetGatewayInfo().GetRegionId() gatewayInfo := measurement.GetGatewayInfo()
hubInfo := measurement.GetHubInfo()
regionID := gatewayInfo.GetRegionId()
if regionID == 0 { if regionID == 0 {
regionID = parseRegionFromTopic(topic) regionID = parseRegionFromTopic(topic)
} }
gatewayMAC := formatMAC(measurement.GetGatewayInfo().GetGatewayMac()) gatewayMAC := formatMAC(gatewayInfo.GetGatewayMac())
packet := measurement.GetStepCountPacket() packet := measurement.GetStepCountPacket()
rssi, snr := parsePacketStatus(measurement.GetPacketStatus()) status := parsePacketStatus(measurement.GetPacketStatus())
beltAddr := fmt.Sprintf("%d-%d", regionID, packet.GetId()) beltAddr := fmt.Sprintf("%d-%d", regionID, packet.GetId())
return models.MqttStepCountRecord{ return models.MqttStepCountRecord{
Identifier: fmt.Sprintf("step:%d:%s:%d:%d", regionID, gatewayMAC, packet.GetId(), packet.GetPacketNum()), Identifier: fmt.Sprintf("step:%d:%s:%d:%d", regionID, gatewayMAC, packet.GetId(), packet.GetPacketNum()),
Topic: topic, Topic: topic,
RegionID: regionID, RegionID: regionID,
GatewayMAC: gatewayMAC, GatewayMAC: gatewayMAC,
BandID: packet.GetId(), GatewaySchemaVersion: gatewayInfo.GetExtra().GetSchemaVersion(),
BeltAddr: beltAddr, GatewayActiveUplink: int32(gatewayInfo.GetExtra().GetActiveUplink().Number()),
PacketNum: packet.GetPacketNum(), GatewayCellularIMEI: gatewayInfo.GetExtra().GetCellularModem().GetImei(),
StepCount: packet.GetStepCount(), GatewayCellularRSSI: gatewayInfo.GetExtra().GetCellularModem().GetRssi(),
SignalRSSINeg: rssi, GatewayCellularBER: gatewayInfo.GetExtra().GetCellularModem().GetBer(),
SNR: snr, BandID: packet.GetId(),
HubBusID: measurement.GetHubInfo().GetBusId(), BeltAddr: beltAddr,
HubSubDevID: measurement.GetHubInfo().GetSubDevId(), PacketNum: packet.GetPacketNum(),
ReceivedAt: now, StepCount: packet.GetStepCount(),
PacketStatusSource: status.source,
SignalRSSINeg: status.signalRSSINeg,
SNR: status.snr,
RawSignalRSSIX2Neg: status.rawSignalRSSIX2Neg,
RawSnrPktX4: status.rawSnrPktX4,
HubBusID: hubInfo.GetBusId(),
HubSubDevID: hubInfo.GetSubDevId(),
HubRadioBW: int32(hubInfo.GetRadioParameters().GetBw().Number()),
HubRadioSF: hubInfo.GetRadioParameters().GetSf(),
HubRadioFrequencyMHz: float64(hubInfo.GetRadioParameters().GetFrequencyMhz()),
ReceivedAt: now,
} }
} }
func buildGatewayStatusRecord(status *whgw_hrpb.GatewayStatus, topic string, now int64) models.MqttGatewayStatusRecord { func buildGatewayStatusRecord(status *whgw_hrpb.GatewayStatus, topic string, now int64) models.MqttGatewayStatusRecord {
regionID := status.GetInfo().GetRegionId() gatewayInfo := status.GetInfo()
regionID := gatewayInfo.GetRegionId()
if regionID == 0 { if regionID == 0 {
regionID = parseRegionFromTopic(topic) regionID = parseRegionFromTopic(topic)
} }
gatewayMAC := formatMAC(status.GetInfo().GetGatewayMac()) gatewayMAC := formatMAC(gatewayInfo.GetGatewayMac())
return models.MqttGatewayStatusRecord{ return models.MqttGatewayStatusRecord{
Identifier: fmt.Sprintf("gateway:%d:%s:%d:%d:%d", regionID, gatewayMAC, status.GetStat().GetBootCount(), status.GetStat().GetUptimeMs(), status.GetStat().GetRxCount()), Identifier: fmt.Sprintf("gateway:%d:%s:%d:%d:%d", regionID, gatewayMAC, status.GetStat().GetBootCount(), status.GetStat().GetUptimeMs(), status.GetStat().GetRxCount()),
Topic: topic, Topic: topic,
RegionID: regionID, RegionID: regionID,
GatewayMAC: gatewayMAC, GatewayMAC: gatewayMAC,
GatewaySchemaVersion: gatewayInfo.GetExtra().GetSchemaVersion(),
GatewayActiveUplink: int32(gatewayInfo.GetExtra().GetActiveUplink().Number()),
GatewayCellularIMEI: gatewayInfo.GetExtra().GetCellularModem().GetImei(),
GatewayCellularRSSI: gatewayInfo.GetExtra().GetCellularModem().GetRssi(),
GatewayCellularBER: gatewayInfo.GetExtra().GetCellularModem().GetBer(),
BootCount: status.GetStat().GetBootCount(), BootCount: status.GetStat().GetBootCount(),
UptimeMs: status.GetStat().GetUptimeMs(), UptimeMs: status.GetStat().GetUptimeMs(),
DurationMsSinceLastPacket: status.GetStat().GetDurationMsSinceLastPacket(), DurationMsSinceLastPacket: status.GetStat().GetDurationMsSinceLastPacket(),
@@ -325,17 +365,27 @@ func buildGatewayStatusRecord(status *whgw_hrpb.GatewayStatus, topic string, now
} }
} }
func parsePacketStatus(status *whgw_hrpb.IPacketStatus) (float64, float64) { func parsePacketStatus(status *whgw_hrpb.IPacketStatus) packetStatusSnapshot {
if status == nil { if status == nil {
return 0, 0 return packetStatusSnapshot{}
} }
if parsed := status.GetParsed(); parsed != nil { if parsed := status.GetParsed(); parsed != nil {
return float64(parsed.GetSignalRssiNeg()), float64(parsed.GetSnrPkt()) return packetStatusSnapshot{
source: "parsed",
signalRSSINeg: float64(parsed.GetSignalRssiNeg()),
snr: float64(parsed.GetSnrPkt()),
}
} }
if raw := status.GetRaw(); raw != nil { if raw := status.GetRaw(); raw != nil {
return -float64(raw.GetSignalRssiX2Neg()) / 2, float64(raw.GetSnrPktX4()) / 4 return packetStatusSnapshot{
source: "raw",
signalRSSINeg: -float64(raw.GetSignalRssiX2Neg()) / 2,
snr: float64(raw.GetSnrPktX4()) / 4,
rawSignalRSSIX2Neg: raw.GetSignalRssiX2Neg(),
rawSnrPktX4: raw.GetSnrPktX4(),
}
} }
return 0, 0 return packetStatusSnapshot{}
} }
func formatMAC(data []byte) string { func formatMAC(data []byte) string {
+735 -345
View File
File diff suppressed because it is too large Load Diff
+118 -31
View File
@@ -5,22 +5,37 @@ package whgw_hr;
option go_package = "hr_receiver/proto;whgw_hrpb"; option go_package = "hr_receiver/proto;whgw_hrpb";
enum HrConfidence { enum HrConfidence {
// [0,25)
ZERO = 0; ZERO = 0;
// [25,50)
LOW = 1; LOW = 1;
// [50,75]
MEDIUM = 2; MEDIUM = 2;
// (75,100]
HIGH = 3; HIGH = 3;
} }
enum LoRaBW { enum LoRaBW {
// nobody is using 7.8 kHz bandwidth
// so to satisfy protobuf, we use NONE for zero value
BW_NONE = 0; BW_NONE = 0;
// 10.4 kHz
BW_10_4 = 0x08; BW_10_4 = 0x08;
// 15.6 kHz
BW_15_6 = 0x01; BW_15_6 = 0x01;
// 20.8 kHz
BW_20_8 = 0x09; BW_20_8 = 0x09;
// 31.25 kHz
BW_31_25 = 0x02; BW_31_25 = 0x02;
// 41.7 kHz
BW_41_7 = 0x0A; BW_41_7 = 0x0A;
// 62.5 kHz
BW_62_5 = 0x03; BW_62_5 = 0x03;
// 125.0 kHz
BW_125_0 = 0x04; BW_125_0 = 0x04;
// 250.0 kHz
BW_250_0 = 0x05; BW_250_0 = 0x05;
// 500.0 kHz
BW_500_0 = 0x06; BW_500_0 = 0x06;
} }
@@ -32,11 +47,12 @@ message LoRaParameters {
message StatusFlag { message StatusFlag {
HrConfidence hr_confidence = 1; HrConfidence hr_confidence = 1;
bool is_active = 2; bool is_active = 2;
bool is_on_skin = 3; bool is_on_skin = 3;
uint32 battery = 4; uint32 battery = 4;
} }
message HrPacket { message HrPacket {
StatusFlag status = 1; StatusFlag status = 1;
uint32 id = 2; uint32 id = 2;
@@ -51,27 +67,51 @@ message StepCountPacket {
} }
message RawPacketStatus { message RawPacketStatus {
// Estimation of RSSI of the LoRa signal (after despreading) on last packet received.
// to get the actual RSSI in dBm, divide by 2 and negate
uint32 signal_rssi_x2_neg = 1; uint32 signal_rssi_x2_neg = 1;
int32 snr_pkt_x4 = 2; // Estimation of RSSI of the LoRa signal (after despreading) on last packet received.
// to get the actual SNR in dB, divide by 4
int32 snr_pkt_x4 = 2;
} }
message PacketStatus { message PacketStatus {
// Estimation of RSSI of the LoRa signal (after despreading) on last packet received.
float signal_rssi_neg = 1; float signal_rssi_neg = 1;
// Estimation of RSSI of the LoRa signal (after despreading) on last packet received.
float snr_pkt = 2; float snr_pkt = 2;
} }
message HubInfo { message HubInfo {
uint32 bus_id = 1; uint32 bus_id = 1;
uint32 sub_dev_id = 2; uint32 sub_dev_id = 2;
/** optional **/
LoRaParameters radio_parameters = 3; LoRaParameters radio_parameters = 3;
} }
message RadioData { message RadioData {
HubInfo hub_info = 1; HubInfo hub_info = 1;
RawPacketStatus raw_packet_status = 2; RawPacketStatus raw_packet_status = 2;
bytes data = 3; bytes data = 3;
} }
/**
NOTIFY (NTF): MISO, unack
SIGNAL (SIG): MOSI, unack
INDICATE (INF): MISO, needs MOSI CONFIRM
CONFIRM (CNF): MOSI, confirms MISO INDICATE
REQUEST (REQ): MOSI, needs MISO RESPONSE
RESPONSE (RSP): MISO, responds to MOSI REQUEST
note that frame type is only about its direction and acknowledge behavior,
the actual semantics are dependent on the payload
*
**/
enum PacketKind { enum PacketKind {
NTF = 0; NTF = 0;
SIG = 1; SIG = 1;
@@ -81,27 +121,57 @@ enum PacketKind {
RSP = 5; RSP = 5;
} }
message GatewayStateReport { enum NetworkUplinkKind {
bool network_has_connection = 1; NETWORK_UPLINK_UNKNOWN = 0;
bool network_has_ip = 2; NETWORK_UPLINK_WIFI = 1;
bool network_has_mqtt_connection = 3; NETWORK_UPLINK_CELLULAR = 2;
bool bluetooth_has_connect = 4;
uint32 error_code = 5;
} }
message CellularModemInfo {
string imei = 1;
int32 rssi = 2;
int32 ber = 3;
}
message GatewayInfoExtra {
uint32 schema_version = 1;
NetworkUplinkKind active_uplink = 2;
CellularModemInfo cellular_modem = 3;
}
message GatewayStateReportExtra {
uint32 schema_version = 1;
NetworkUplinkKind selected_uplink = 2;
NetworkUplinkKind active_uplink = 3;
bool cellular_modem_present = 4;
}
message GatewayStateReport {
bool network_has_connection = 1;
bool network_has_ip = 2;
bool network_has_mqtt_connection = 3;
bool bluetooth_has_connect = 4;
uint32 error_code = 5;
GatewayStateReportExtra extra = 6;
}
/*** Hub (S) to Gateway (M) ***/
message HubSlaveOutGatewayMasterInMsg { message HubSlaveOutGatewayMasterInMsg {
oneof choice { oneof choice {
RadioData ntf_radio_data = 1; RadioData ntf_radio_data = 1;
BatteryInfo ntf_battery_info = 2; BatteryInfo ntf_battery_info = 2;
} }
} }
/*** Gateway (M) to Hub (S) ***/
message GatewayMasterOutHubSlaveInMsg { message GatewayMasterOutHubSlaveInMsg {
oneof choice { oneof choice {
GatewayStateReport sig_gateway_state_report = 1; GatewayStateReport sig_gateway_state_report = 1;
} }
} }
/*** Gateway to MQTT ***/
message GatewaySlaveOutCloudMasterInMsg { message GatewaySlaveOutCloudMasterInMsg {
oneof choice { oneof choice {
HrMeasurement ntf_hr_measurement = 1; HrMeasurement ntf_hr_measurement = 1;
@@ -110,6 +180,8 @@ message GatewaySlaveOutCloudMasterInMsg {
} }
} }
/** note that the endpoint should be v2 **/
message BatteryInfo { message BatteryInfo {
uint32 voltage_mv = 1; uint32 voltage_mv = 1;
uint32 soc_percentage = 2; uint32 soc_percentage = 2;
@@ -118,52 +190,64 @@ message BatteryInfo {
message GatewayInfo { message GatewayInfo {
uint32 region_id = 1; uint32 region_id = 1;
bytes gateway_mac = 2; bytes gateway_mac = 2;
GatewayInfoExtra extra = 3;
} }
message IPacketStatus { message IPacketStatus {
oneof choice { oneof choice {
RawPacketStatus raw = 1; RawPacketStatus raw = 1;
PacketStatus parsed = 2; PacketStatus parsed = 2;
} }
} }
message HrMeasurement { message HrMeasurement {
HrPacket hr_packet = 1; HrPacket hr_packet = 1;
IPacketStatus packet_status = 2; IPacketStatus packet_status = 2;
GatewayInfo gateway_info = 3; GatewayInfo gateway_info = 3;
HubInfo hub_info = 4; HubInfo hub_info = 4;
} }
message StepCountMeasurement { message StepCountMeasurement {
StepCountPacket step_count_packet = 1; StepCountPacket step_count_packet = 1;
IPacketStatus packet_status = 2; IPacketStatus packet_status = 2;
GatewayInfo gateway_info = 3; GatewayInfo gateway_info = 3;
HubInfo hub_info = 4; HubInfo hub_info = 4;
} }
message GatewayStatistic { message GatewayStatistic {
uint32 boot_count = 1; // Number of times the gateway has booted in history
uint32 uptime_ms = 2; uint32 boot_count = 1;
uint32 duration_ms_since_last_packet = 3; // Uptime of the device (in ms)
uint32 rx_count = 4; uint32 uptime_ms = 2;
// Duration (in ms) since last packet received
// would be the duration since boot if no packets received yet
uint32 duration_ms_since_last_packet = 3;
// Total number of packets received since boot
uint32 rx_count = 4;
// optional, battery info
BatteryInfo battery_info = 5; BatteryInfo battery_info = 5;
} }
message GatewayStatus { message GatewayStatus {
GatewayInfo info = 1; GatewayInfo info = 1;
GatewayStatistic stat = 2; GatewayStatistic stat = 2;
} }
message Status { message Status {
int32 code = 1; int32 code = 1;
string message = 2; string message = 2;
} }
/** Gateway Configuration Messages **/
/** Master is Gateway; Slave is config client (bluetooth central, phone etc.) **/
enum GatewayConfigEntryKind { enum GatewayConfigEntryKind {
REGION_ID = 0; REGION_ID = 0;
WIFI_SSID = 1; WIFI_SSID = 1;
WIFI_PASSWORD = 2; WIFI_PASSWORD = 2;
NETWORK_UPLINK = 3;
CELLULAR_APN = 4;
} }
message GatewayConfigEntry { message GatewayConfigEntry {
@@ -171,14 +255,16 @@ message GatewayConfigEntry {
uint32 region_id = 1; uint32 region_id = 1;
string wifi_ssid = 2; string wifi_ssid = 2;
string wifi_password = 3; string wifi_password = 3;
NetworkUplinkKind network_uplink = 4;
string cellular_apn = 5;
} }
} }
message GatewayConfigMasterOutSlaveInMsg { message GatewayConfigMasterOutSlaveInMsg {
oneof choice { oneof choice {
GatewayConfigEntry cnf_get_entry = 1; GatewayConfigEntry cnf_get_entry = 1;
Status cnf_get_failure = 2; Status cnf_get_failure = 2;
Status cnf_set_entry = 3; Status cnf_set_entry = 3;
} }
} }
@@ -188,3 +274,4 @@ message GatewayConfigMasterInSlaveOutMsg {
GatewayConfigEntry inf_set_entry = 2; GatewayConfigEntry inf_set_entry = 2;
} }
} }