Compare commits

...

12 Commits

Author SHA1 Message Date
d6cc9d4fd6 Bump version to 4.0.3-test.1 2022-10-21 07:37:25 +01:00
289d97f258 Implement dev_addr_prefixes configuration.
This makes it possible to configure one or multiple DevAddr sub-ranges
instead of using the whole DevAddr range provided by the configured
NetID.

Closes #49.
2022-10-19 12:53:34 +01:00
6cc813aed1 Implement DevAddrPrefix type.
This type defines the (NetID derived) prefix that must be used when
generating device addresses. This can be retrieved from the NetID, but
it is also possible to define a prefix that defines a smaller address
range within the NetID.

See also #49.
2022-10-19 12:03:55 +01:00
e04f991e76 Fix 'Cannot serialize NaN as google.protobuf.Value.number_value'.
In case the codec returns a NaN float, this is converted to None to
avoid Protobuf serialization error. This also fixes the eventlog such
that it does not break out of the loop (unless it is a channel error).
Messages that can't be processed will be ignored and an error is
printed.

Fixes https://github.com/chirpstack/chirpstack-v3-to-v4/issues/4.
2022-10-06 12:31:11 +01:00
5f4d03f3e4 Add example for reading frame-logs from Redis Streams. 2022-10-04 15:50:20 +01:00
94455ffe35 Fix typo (:: > :). 2022-10-04 15:50:20 +01:00
601d3f9aa1 Use trust_store instead of ca_path for mqtt integration. (#47) 2022-10-04 15:44:59 +01:00
4282d3aedc Update clap to v4. 2022-10-03 15:11:53 +01:00
a91fb1f73e Bump version to 4.0.2 2022-09-28 13:05:13 +01:00
b19038e664 Update README. 2022-09-28 12:55:48 +01:00
0940260541 Fix client_cert_lifetime value in configfile template. 2022-09-28 12:38:37 +01:00
51b622e8e2 Fix terminating stream loop on client disconnect.
As the spawn_blocking thread is not terminated when the frame_log_future
is dropped, it would keep the Redis connection open. By closing the
redis_rx channel on client-disconnect, we can check if the channel has
been closed inside the spawn_blocking thread, and return if this is the
case.

Closes #40.
2022-09-28 12:25:33 +01:00
46 changed files with 844 additions and 3038 deletions

51
Cargo.lock generated
View File

@ -672,7 +672,7 @@ dependencies = [
[[package]]
name = "backend"
version = "4.0.1"
version = "4.0.3-test.1"
dependencies = [
"aes-kw",
"anyhow",
@ -731,7 +731,7 @@ dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"clap",
"clap 3.2.22",
"env_logger",
"lazy_static",
"lazycell",
@ -889,7 +889,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chirpstack"
version = "4.0.1"
version = "4.0.3-test.1"
dependencies = [
"aes",
"anyhow",
@ -904,7 +904,7 @@ dependencies = [
"bytes",
"chirpstack_api",
"chrono",
"clap",
"clap 4.0.8",
"diesel",
"diesel_migrations",
"futures",
@ -968,7 +968,7 @@ dependencies = [
[[package]]
name = "chirpstack_api"
version = "4.0.1"
version = "4.0.3-test.1"
dependencies = [
"hex",
"pbjson",
@ -1028,13 +1028,41 @@ checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
dependencies = [
"atty",
"bitflags",
"clap_lex",
"clap_lex 0.2.4",
"indexmap",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap"
version = "4.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5840cd9093aabeabf7fd932754c435b7674520fc3ddc935c397837050f0f1e4b"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex 0.3.0",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92289ffc6fb4a85d85c246ddb874c05a87a2e540fb6ad52f7ca07c8c1e1840b1"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
@ -1044,6 +1072,15 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "cmac"
version = "0.7.1"
@ -2170,7 +2207,7 @@ dependencies = [
[[package]]
name = "lrwn"
version = "4.0.1"
version = "4.0.3-test.1"
dependencies = [
"aes",
"anyhow",

View File

@ -5,25 +5,14 @@
ChirpStack is an open-source LoRaWAN Network Server, part of the
[ChirpStack](https://www.chirpstack.io/) project.
**Note:** this repository contains the source of what is going to be
ChirpStack v4. This release merges the ChirpStack Network Server and
ChirpStack Application Server components into a single service, making
it a lot easier to setup a multi-region ChirpStack instance. This is
still work in progress.
This repository contains the source-code of ChirpStack v4, which merges the
ChirpStack Application Server (v3) and ChirpStack Network Server (v3) into a
single binary, making it easier to setup and use.
Please refer to the forum announcement for background information:
https://forum.chirpstack.io/t/changes-coming-to-chirpstack/13101
## Documentation
## Testing / building from source
To build ChirpStack from source, run the following command:
```bash
make test-server
```
Note: this requires a Linux environment With Docker and Docker Compose
setup. Pre-compiled (test) binaries will be provided soon.
Please refer to the [ChirpStack](https://www.chirpstack.io/) website for
documentation.
## License

View File

@ -1,6 +1,6 @@
{
"name": "@chirpstack/chirpstack-api-grpc-web",
"version": "4.0.1",
"version": "4.0.3-test.1",
"description": "Chirpstack gRPC-web API",
"license": "MIT",
"devDependencies": {

2
api/js/package.json vendored
View File

@ -1,6 +1,6 @@
{
"name": "@chirpstack/chirpstack-api",
"version": "4.0.1",
"version": "4.0.3-test.1",
"description": "Chirpstack JS and TS API",
"license": "MIT",
"devDependencies": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,10 +2,9 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: chirpstack-api/api/device_profile_template.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
@ -21,99 +20,8 @@ from chirpstack_api.api import device_profile_pb2 as chirpstack__api_dot_api_dot
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n0chirpstack-api/api/device_profile_template.proto\x12\x03\x61pi\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\"chirpstack-api/common/common.proto\x1a\'chirpstack-api/api/device_profile.proto\"\xd6\x07\n\x15\x44\x65viceProfileTemplate\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x0e\n\x06vendor\x18\x04 \x01(\t\x12\x10\n\x08\x66irmware\x18\x05 \x01(\t\x12\x1e\n\x06region\x18\x06 \x01(\x0e\x32\x0e.common.Region\x12\'\n\x0bmac_version\x18\x07 \x01(\x0e\x32\x12.common.MacVersion\x12\x36\n\x13reg_params_revision\x18\x08 \x01(\x0e\x32\x19.common.RegParamsRevision\x12\x18\n\x10\x61\x64r_algorithm_id\x18\t \x01(\t\x12\x30\n\x15payload_codec_runtime\x18\n \x01(\x0e\x32\x11.api.CodecRuntime\x12\x1c\n\x14payload_codec_script\x18\x0b \x01(\t\x12\x1f\n\x17\x66lush_queue_on_activate\x18\x0c \x01(\x08\x12\x17\n\x0fuplink_interval\x18\r \x01(\r\x12\"\n\x1a\x64\x65vice_status_req_interval\x18\x0e \x01(\r\x12\x15\n\rsupports_otaa\x18\x0f \x01(\x08\x12\x18\n\x10supports_class_b\x18\x10 \x01(\x08\x12\x18\n\x10supports_class_c\x18\x11 \x01(\x08\x12\x17\n\x0f\x63lass_b_timeout\x18\x12 \x01(\r\x12 \n\x18\x63lass_b_ping_slot_period\x18\x13 \x01(\r\x12\x1c\n\x14\x63lass_b_ping_slot_dr\x18\x14 \x01(\r\x12\x1e\n\x16\x63lass_b_ping_slot_freq\x18\x15 \x01(\r\x12\x17\n\x0f\x63lass_c_timeout\x18\x16 \x01(\r\x12\x15\n\rabp_rx1_delay\x18\x17 \x01(\r\x12\x19\n\x11\x61\x62p_rx1_dr_offset\x18\x18 \x01(\r\x12\x12\n\nabp_rx2_dr\x18\x19 \x01(\r\x12\x14\n\x0c\x61\x62p_rx2_freq\x18\x1a \x01(\r\x12\x32\n\x04tags\x18\x1b \x03(\x0b\x32$.api.DeviceProfileTemplate.TagsEntry\x12\x42\n\x0cmeasurements\x18\x1c \x03(\x0b\x32,.api.DeviceProfileTemplate.MeasurementsEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x45\n\x11MeasurementsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1f\n\x05value\x18\x02 \x01(\x0b\x32\x10.api.Measurement:\x02\x38\x01\"\x87\x03\n\x1d\x44\x65viceProfileTemplateListItem\x12\n\n\x02id\x18\x01 \x01(\t\x12.\n\ncreated_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x0e\n\x06vendor\x18\x05 \x01(\t\x12\x10\n\x08\x66irmware\x18\x06 \x01(\t\x12\x1e\n\x06region\x18\x07 \x01(\x0e\x32\x0e.common.Region\x12\'\n\x0bmac_version\x18\x08 \x01(\x0e\x32\x12.common.MacVersion\x12\x36\n\x13reg_params_revision\x18\t \x01(\x0e\x32\x19.common.RegParamsRevision\x12\x15\n\rsupports_otaa\x18\n \x01(\x08\x12\x18\n\x10supports_class_b\x18\x0b \x01(\x08\x12\x18\n\x10supports_class_c\x18\x0c \x01(\x08\"a\n\"CreateDeviceProfileTemplateRequest\x12;\n\x17\x64\x65vice_profile_template\x18\x01 \x01(\x0b\x32\x1a.api.DeviceProfileTemplate\"-\n\x1fGetDeviceProfileTemplateRequest\x12\n\n\x02id\x18\x01 \x01(\t\"\xbf\x01\n GetDeviceProfileTemplateResponse\x12;\n\x17\x64\x65vice_profile_template\x18\x01 \x01(\x0b\x32\x1a.api.DeviceProfileTemplate\x12.\n\ncreated_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"a\n\"UpdateDeviceProfileTemplateRequest\x12;\n\x17\x64\x65vice_profile_template\x18\x01 \x01(\x0b\x32\x1a.api.DeviceProfileTemplate\"0\n\"DeleteDeviceProfileTemplateRequest\x12\n\n\x02id\x18\x01 \x01(\t\"B\n!ListDeviceProfileTemplatesRequest\x12\r\n\x05limit\x18\x01 \x01(\r\x12\x0e\n\x06offset\x18\x02 \x01(\r\"m\n\"ListDeviceProfileTemplatesResponse\x12\x13\n\x0btotal_count\x18\x01 \x01(\r\x12\x32\n\x06result\x18\x02 \x03(\x0b\x32\".api.DeviceProfileTemplateListItem2\x9d\x05\n\x1c\x44\x65viceProfileTemplateService\x12s\n\x06\x43reate\x12\'.api.CreateDeviceProfileTemplateRequest\x1a\x16.google.protobuf.Empty\"(\x82\xd3\xe4\x93\x02\"\"\x1d/api/device-profile-templates:\x01*\x12~\n\x03Get\x12$.api.GetDeviceProfileTemplateRequest\x1a%.api.GetDeviceProfileTemplateResponse\"*\x82\xd3\xe4\x93\x02$\x12\"/api/device-profile-templates/{id}\x12\x90\x01\n\x06Update\x12\'.api.UpdateDeviceProfileTemplateRequest\x1a\x16.google.protobuf.Empty\"E\x82\xd3\xe4\x93\x02?\x1a:/api/device-profile-templates/{device_profile_template.id}:\x01*\x12u\n\x06\x44\x65lete\x12\'.api.DeleteDeviceProfileTemplateRequest\x1a\x16.google.protobuf.Empty\"*\x82\xd3\xe4\x93\x02$*\"/api/device-profile-templates/{id}\x12~\n\x04List\x12&.api.ListDeviceProfileTemplatesRequest\x1a\'.api.ListDeviceProfileTemplatesResponse\"%\x82\xd3\xe4\x93\x02\x1f\x12\x1d/api/device-profile-templatesBa\n\x11io.chirpstack.apiB\x1a\x44\x65viceProfileTemplateProtoP\x01Z.github.com/chirpstack/chirpstack/api/go/v4/apib\x06proto3')
_DEVICEPROFILETEMPLATE = DESCRIPTOR.message_types_by_name['DeviceProfileTemplate']
_DEVICEPROFILETEMPLATE_TAGSENTRY = _DEVICEPROFILETEMPLATE.nested_types_by_name['TagsEntry']
_DEVICEPROFILETEMPLATE_MEASUREMENTSENTRY = _DEVICEPROFILETEMPLATE.nested_types_by_name['MeasurementsEntry']
_DEVICEPROFILETEMPLATELISTITEM = DESCRIPTOR.message_types_by_name['DeviceProfileTemplateListItem']
_CREATEDEVICEPROFILETEMPLATEREQUEST = DESCRIPTOR.message_types_by_name['CreateDeviceProfileTemplateRequest']
_GETDEVICEPROFILETEMPLATEREQUEST = DESCRIPTOR.message_types_by_name['GetDeviceProfileTemplateRequest']
_GETDEVICEPROFILETEMPLATERESPONSE = DESCRIPTOR.message_types_by_name['GetDeviceProfileTemplateResponse']
_UPDATEDEVICEPROFILETEMPLATEREQUEST = DESCRIPTOR.message_types_by_name['UpdateDeviceProfileTemplateRequest']
_DELETEDEVICEPROFILETEMPLATEREQUEST = DESCRIPTOR.message_types_by_name['DeleteDeviceProfileTemplateRequest']
_LISTDEVICEPROFILETEMPLATESREQUEST = DESCRIPTOR.message_types_by_name['ListDeviceProfileTemplatesRequest']
_LISTDEVICEPROFILETEMPLATESRESPONSE = DESCRIPTOR.message_types_by_name['ListDeviceProfileTemplatesResponse']
DeviceProfileTemplate = _reflection.GeneratedProtocolMessageType('DeviceProfileTemplate', (_message.Message,), {
'TagsEntry' : _reflection.GeneratedProtocolMessageType('TagsEntry', (_message.Message,), {
'DESCRIPTOR' : _DEVICEPROFILETEMPLATE_TAGSENTRY,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.DeviceProfileTemplate.TagsEntry)
})
,
'MeasurementsEntry' : _reflection.GeneratedProtocolMessageType('MeasurementsEntry', (_message.Message,), {
'DESCRIPTOR' : _DEVICEPROFILETEMPLATE_MEASUREMENTSENTRY,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.DeviceProfileTemplate.MeasurementsEntry)
})
,
'DESCRIPTOR' : _DEVICEPROFILETEMPLATE,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.DeviceProfileTemplate)
})
_sym_db.RegisterMessage(DeviceProfileTemplate)
_sym_db.RegisterMessage(DeviceProfileTemplate.TagsEntry)
_sym_db.RegisterMessage(DeviceProfileTemplate.MeasurementsEntry)
DeviceProfileTemplateListItem = _reflection.GeneratedProtocolMessageType('DeviceProfileTemplateListItem', (_message.Message,), {
'DESCRIPTOR' : _DEVICEPROFILETEMPLATELISTITEM,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.DeviceProfileTemplateListItem)
})
_sym_db.RegisterMessage(DeviceProfileTemplateListItem)
CreateDeviceProfileTemplateRequest = _reflection.GeneratedProtocolMessageType('CreateDeviceProfileTemplateRequest', (_message.Message,), {
'DESCRIPTOR' : _CREATEDEVICEPROFILETEMPLATEREQUEST,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.CreateDeviceProfileTemplateRequest)
})
_sym_db.RegisterMessage(CreateDeviceProfileTemplateRequest)
GetDeviceProfileTemplateRequest = _reflection.GeneratedProtocolMessageType('GetDeviceProfileTemplateRequest', (_message.Message,), {
'DESCRIPTOR' : _GETDEVICEPROFILETEMPLATEREQUEST,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.GetDeviceProfileTemplateRequest)
})
_sym_db.RegisterMessage(GetDeviceProfileTemplateRequest)
GetDeviceProfileTemplateResponse = _reflection.GeneratedProtocolMessageType('GetDeviceProfileTemplateResponse', (_message.Message,), {
'DESCRIPTOR' : _GETDEVICEPROFILETEMPLATERESPONSE,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.GetDeviceProfileTemplateResponse)
})
_sym_db.RegisterMessage(GetDeviceProfileTemplateResponse)
UpdateDeviceProfileTemplateRequest = _reflection.GeneratedProtocolMessageType('UpdateDeviceProfileTemplateRequest', (_message.Message,), {
'DESCRIPTOR' : _UPDATEDEVICEPROFILETEMPLATEREQUEST,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.UpdateDeviceProfileTemplateRequest)
})
_sym_db.RegisterMessage(UpdateDeviceProfileTemplateRequest)
DeleteDeviceProfileTemplateRequest = _reflection.GeneratedProtocolMessageType('DeleteDeviceProfileTemplateRequest', (_message.Message,), {
'DESCRIPTOR' : _DELETEDEVICEPROFILETEMPLATEREQUEST,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.DeleteDeviceProfileTemplateRequest)
})
_sym_db.RegisterMessage(DeleteDeviceProfileTemplateRequest)
ListDeviceProfileTemplatesRequest = _reflection.GeneratedProtocolMessageType('ListDeviceProfileTemplatesRequest', (_message.Message,), {
'DESCRIPTOR' : _LISTDEVICEPROFILETEMPLATESREQUEST,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.ListDeviceProfileTemplatesRequest)
})
_sym_db.RegisterMessage(ListDeviceProfileTemplatesRequest)
ListDeviceProfileTemplatesResponse = _reflection.GeneratedProtocolMessageType('ListDeviceProfileTemplatesResponse', (_message.Message,), {
'DESCRIPTOR' : _LISTDEVICEPROFILETEMPLATESRESPONSE,
'__module__' : 'chirpstack_api.api.device_profile_template_pb2'
# @@protoc_insertion_point(class_scope:api.ListDeviceProfileTemplatesResponse)
})
_sym_db.RegisterMessage(ListDeviceProfileTemplatesResponse)
_DEVICEPROFILETEMPLATESERVICE = DESCRIPTOR.services_by_name['DeviceProfileTemplateService']
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chirpstack_api.api.device_profile_template_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None

View File

@ -2,10 +2,9 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: chirpstack-api/api/frame_log.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
@ -19,24 +18,8 @@ from chirpstack_api.gw import gw_pb2 as chirpstack__api_dot_gw_dot_gw__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"chirpstack-api/api/frame_log.proto\x12\x03\x61pi\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\"chirpstack-api/common/common.proto\x1a\x1a\x63hirpstack-api/gw/gw.proto\"\xf7\x01\n\x0eUplinkFrameLog\x12\x13\n\x0bphy_payload\x18\x01 \x01(\x0c\x12!\n\x07tx_info\x18\x02 \x01(\x0b\x32\x10.gw.UplinkTxInfo\x12!\n\x07rx_info\x18\x03 \x03(\x0b\x32\x10.gw.UplinkRxInfo\x12\x1d\n\x06m_type\x18\x04 \x01(\x0e\x32\r.common.MType\x12\x10\n\x08\x64\x65v_addr\x18\x05 \x01(\t\x12\x0f\n\x07\x64\x65v_eui\x18\x06 \x01(\t\x12(\n\x04time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1e\n\x16plaintext_mac_commands\x18\x08 \x01(\x08\"\x81\x02\n\x10\x44ownlinkFrameLog\x12(\n\x04time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x13\n\x0bphy_payload\x18\x02 \x01(\x0c\x12#\n\x07tx_info\x18\x03 \x01(\x0b\x32\x12.gw.DownlinkTxInfo\x12\x13\n\x0b\x64ownlink_id\x18\x04 \x01(\r\x12\x12\n\ngateway_id\x18\x05 \x01(\t\x12\x1d\n\x06m_type\x18\x06 \x01(\x0e\x32\r.common.MType\x12\x10\n\x08\x64\x65v_addr\x18\x07 \x01(\t\x12\x0f\n\x07\x64\x65v_eui\x18\x08 \x01(\t\x12\x1e\n\x16plaintext_mac_commands\x18\t \x01(\x08\x42T\n\x11io.chirpstack.apiB\rFrameLogProtoP\x01Z.github.com/chirpstack/chirpstack/api/go/v4/apib\x06proto3')
_UPLINKFRAMELOG = DESCRIPTOR.message_types_by_name['UplinkFrameLog']
_DOWNLINKFRAMELOG = DESCRIPTOR.message_types_by_name['DownlinkFrameLog']
UplinkFrameLog = _reflection.GeneratedProtocolMessageType('UplinkFrameLog', (_message.Message,), {
'DESCRIPTOR' : _UPLINKFRAMELOG,
'__module__' : 'chirpstack_api.api.frame_log_pb2'
# @@protoc_insertion_point(class_scope:api.UplinkFrameLog)
})
_sym_db.RegisterMessage(UplinkFrameLog)
DownlinkFrameLog = _reflection.GeneratedProtocolMessageType('DownlinkFrameLog', (_message.Message,), {
'DESCRIPTOR' : _DOWNLINKFRAMELOG,
'__module__' : 'chirpstack_api.api.frame_log_pb2'
# @@protoc_insertion_point(class_scope:api.DownlinkFrameLog)
})
_sym_db.RegisterMessage(DownlinkFrameLog)
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chirpstack_api.api.frame_log_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None

View File

@ -2,10 +2,9 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: chirpstack-api/api/gateway.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
@ -20,140 +19,8 @@ from chirpstack_api.common import common_pb2 as chirpstack__api_dot_common_dot_c
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n chirpstack-api/api/gateway.proto\x12\x03\x61pi\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\"chirpstack-api/common/common.proto\"\xaf\x02\n\x07Gateway\x12\x12\n\ngateway_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\"\n\x08location\x18\x04 \x01(\x0b\x32\x10.common.Location\x12\x11\n\ttenant_id\x18\x05 \x01(\t\x12$\n\x04tags\x18\x06 \x03(\x0b\x32\x16.api.Gateway.TagsEntry\x12\x30\n\nproperties\x18\x07 \x03(\x0b\x32\x1c.api.Gateway.PropertiesEntry\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x31\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xfe\x02\n\x0fGatewayListItem\x12\x11\n\ttenant_id\x18\x01 \x01(\t\x12\x12\n\ngateway_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x04 \x01(\t\x12\"\n\x08location\x18\x05 \x01(\x0b\x32\x10.common.Location\x12\x38\n\nproperties\x18\x06 \x03(\x0b\x32$.api.GatewayListItem.PropertiesEntry\x12.\n\ncreated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0clast_seen_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\x31\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"5\n\x14\x43reateGatewayRequest\x12\x1d\n\x07gateway\x18\x01 \x01(\x0b\x32\x0c.api.Gateway\"\'\n\x11GetGatewayRequest\x12\x12\n\ngateway_id\x18\x01 \x01(\t\"\xc5\x01\n\x12GetGatewayResponse\x12\x1d\n\x07gateway\x18\x01 \x01(\x0b\x32\x0c.api.Gateway\x12.\n\ncreated_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0clast_seen_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"5\n\x14UpdateGatewayRequest\x12\x1d\n\x07gateway\x18\x01 \x01(\x0b\x32\x0c.api.Gateway\"*\n\x14\x44\x65leteGatewayRequest\x12\x12\n\ngateway_id\x18\x01 \x01(\t\"W\n\x13ListGatewaysRequest\x12\r\n\x05limit\x18\x01 \x01(\r\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x0e\n\x06search\x18\x03 \x01(\t\x12\x11\n\ttenant_id\x18\x04 \x01(\t\"Q\n\x14ListGatewaysResponse\x12\x13\n\x0btotal_count\x18\x01 \x01(\r\x12$\n\x06result\x18\x02 \x03(\x0b\x32\x14.api.GatewayListItem\"=\n\'GenerateGatewayClientCertificateRequest\x12\x12\n\ngateway_id\x18\x01 \x01(\t\"\x8e\x01\n(GenerateGatewayClientCertificateResponse\x12\x10\n\x08tls_cert\x18\x01 \x01(\t\x12\x0f\n\x07tls_key\x18\x02 \x01(\t\x12\x0f\n\x07\x63\x61_cert\x18\x03 \x01(\t\x12.\n\nexpires_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xac\x01\n\x18GetGatewayMetricsRequest\x12\x12\n\ngateway_id\x18\x01 \x01(\t\x12)\n\x05start\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\'\n\x03\x65nd\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12(\n\x0b\x61ggregation\x18\x04 \x01(\x0e\x32\x13.common.Aggregation\"\xc2\x02\n\x19GetGatewayMetricsResponse\x12\"\n\nrx_packets\x18\x01 \x01(\x0b\x32\x0e.common.Metric\x12\"\n\ntx_packets\x18\x02 \x01(\x0b\x32\x0e.common.Metric\x12+\n\x13tx_packets_per_freq\x18\x03 \x01(\x0b\x32\x0e.common.Metric\x12+\n\x13rx_packets_per_freq\x18\x04 \x01(\x0b\x32\x0e.common.Metric\x12)\n\x11tx_packets_per_dr\x18\x05 \x01(\x0b\x32\x0e.common.Metric\x12)\n\x11rx_packets_per_dr\x18\x06 \x01(\x0b\x32\x0e.common.Metric\x12-\n\x15tx_packets_per_status\x18\x07 \x01(\x0b\x32\x0e.common.Metric2\x91\x06\n\x0eGatewayService\x12U\n\x06\x43reate\x12\x19.api.CreateGatewayRequest\x1a\x16.google.protobuf.Empty\"\x18\x82\xd3\xe4\x93\x02\x12\"\r/api/gateways:\x01*\x12Z\n\x03Get\x12\x16.api.GetGatewayRequest\x1a\x17.api.GetGatewayResponse\"\"\x82\xd3\xe4\x93\x02\x1c\x12\x1a/api/gateways/{gateway_id}\x12j\n\x06Update\x12\x19.api.UpdateGatewayRequest\x1a\x16.google.protobuf.Empty\"-\x82\xd3\xe4\x93\x02\'\x1a\"/api/gateways/{gateway.gateway_id}:\x01*\x12_\n\x06\x44\x65lete\x12\x19.api.DeleteGatewayRequest\x1a\x16.google.protobuf.Empty\"\"\x82\xd3\xe4\x93\x02\x1c*\x1a/api/gateways/{gateway_id}\x12R\n\x04List\x12\x18.api.ListGatewaysRequest\x1a\x19.api.ListGatewaysResponse\"\x15\x82\xd3\xe4\x93\x02\x0f\x12\r/api/gateways\x12\xb1\x01\n\x19GenerateClientCertificate\x12,.api.GenerateGatewayClientCertificateRequest\x1a-.api.GenerateGatewayClientCertificateResponse\"7\x82\xd3\xe4\x93\x02\x31\"//api/gateways/{gateway_id}/generate-certificate\x12w\n\nGetMetrics\x12\x1d.api.GetGatewayMetricsRequest\x1a\x1e.api.GetGatewayMetricsResponse\"*\x82\xd3\xe4\x93\x02$\x12\"/api/gateways/{gateway_id}/metricsBS\n\x11io.chirpstack.apiB\x0cGatewayProtoP\x01Z.github.com/chirpstack/chirpstack/api/go/v4/apib\x06proto3')
_GATEWAY = DESCRIPTOR.message_types_by_name['Gateway']
_GATEWAY_TAGSENTRY = _GATEWAY.nested_types_by_name['TagsEntry']
_GATEWAY_PROPERTIESENTRY = _GATEWAY.nested_types_by_name['PropertiesEntry']
_GATEWAYLISTITEM = DESCRIPTOR.message_types_by_name['GatewayListItem']
_GATEWAYLISTITEM_PROPERTIESENTRY = _GATEWAYLISTITEM.nested_types_by_name['PropertiesEntry']
_CREATEGATEWAYREQUEST = DESCRIPTOR.message_types_by_name['CreateGatewayRequest']
_GETGATEWAYREQUEST = DESCRIPTOR.message_types_by_name['GetGatewayRequest']
_GETGATEWAYRESPONSE = DESCRIPTOR.message_types_by_name['GetGatewayResponse']
_UPDATEGATEWAYREQUEST = DESCRIPTOR.message_types_by_name['UpdateGatewayRequest']
_DELETEGATEWAYREQUEST = DESCRIPTOR.message_types_by_name['DeleteGatewayRequest']
_LISTGATEWAYSREQUEST = DESCRIPTOR.message_types_by_name['ListGatewaysRequest']
_LISTGATEWAYSRESPONSE = DESCRIPTOR.message_types_by_name['ListGatewaysResponse']
_GENERATEGATEWAYCLIENTCERTIFICATEREQUEST = DESCRIPTOR.message_types_by_name['GenerateGatewayClientCertificateRequest']
_GENERATEGATEWAYCLIENTCERTIFICATERESPONSE = DESCRIPTOR.message_types_by_name['GenerateGatewayClientCertificateResponse']
_GETGATEWAYMETRICSREQUEST = DESCRIPTOR.message_types_by_name['GetGatewayMetricsRequest']
_GETGATEWAYMETRICSRESPONSE = DESCRIPTOR.message_types_by_name['GetGatewayMetricsResponse']
Gateway = _reflection.GeneratedProtocolMessageType('Gateway', (_message.Message,), {
'TagsEntry' : _reflection.GeneratedProtocolMessageType('TagsEntry', (_message.Message,), {
'DESCRIPTOR' : _GATEWAY_TAGSENTRY,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.Gateway.TagsEntry)
})
,
'PropertiesEntry' : _reflection.GeneratedProtocolMessageType('PropertiesEntry', (_message.Message,), {
'DESCRIPTOR' : _GATEWAY_PROPERTIESENTRY,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.Gateway.PropertiesEntry)
})
,
'DESCRIPTOR' : _GATEWAY,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.Gateway)
})
_sym_db.RegisterMessage(Gateway)
_sym_db.RegisterMessage(Gateway.TagsEntry)
_sym_db.RegisterMessage(Gateway.PropertiesEntry)
GatewayListItem = _reflection.GeneratedProtocolMessageType('GatewayListItem', (_message.Message,), {
'PropertiesEntry' : _reflection.GeneratedProtocolMessageType('PropertiesEntry', (_message.Message,), {
'DESCRIPTOR' : _GATEWAYLISTITEM_PROPERTIESENTRY,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GatewayListItem.PropertiesEntry)
})
,
'DESCRIPTOR' : _GATEWAYLISTITEM,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GatewayListItem)
})
_sym_db.RegisterMessage(GatewayListItem)
_sym_db.RegisterMessage(GatewayListItem.PropertiesEntry)
CreateGatewayRequest = _reflection.GeneratedProtocolMessageType('CreateGatewayRequest', (_message.Message,), {
'DESCRIPTOR' : _CREATEGATEWAYREQUEST,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.CreateGatewayRequest)
})
_sym_db.RegisterMessage(CreateGatewayRequest)
GetGatewayRequest = _reflection.GeneratedProtocolMessageType('GetGatewayRequest', (_message.Message,), {
'DESCRIPTOR' : _GETGATEWAYREQUEST,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GetGatewayRequest)
})
_sym_db.RegisterMessage(GetGatewayRequest)
GetGatewayResponse = _reflection.GeneratedProtocolMessageType('GetGatewayResponse', (_message.Message,), {
'DESCRIPTOR' : _GETGATEWAYRESPONSE,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GetGatewayResponse)
})
_sym_db.RegisterMessage(GetGatewayResponse)
UpdateGatewayRequest = _reflection.GeneratedProtocolMessageType('UpdateGatewayRequest', (_message.Message,), {
'DESCRIPTOR' : _UPDATEGATEWAYREQUEST,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.UpdateGatewayRequest)
})
_sym_db.RegisterMessage(UpdateGatewayRequest)
DeleteGatewayRequest = _reflection.GeneratedProtocolMessageType('DeleteGatewayRequest', (_message.Message,), {
'DESCRIPTOR' : _DELETEGATEWAYREQUEST,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.DeleteGatewayRequest)
})
_sym_db.RegisterMessage(DeleteGatewayRequest)
ListGatewaysRequest = _reflection.GeneratedProtocolMessageType('ListGatewaysRequest', (_message.Message,), {
'DESCRIPTOR' : _LISTGATEWAYSREQUEST,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.ListGatewaysRequest)
})
_sym_db.RegisterMessage(ListGatewaysRequest)
ListGatewaysResponse = _reflection.GeneratedProtocolMessageType('ListGatewaysResponse', (_message.Message,), {
'DESCRIPTOR' : _LISTGATEWAYSRESPONSE,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.ListGatewaysResponse)
})
_sym_db.RegisterMessage(ListGatewaysResponse)
GenerateGatewayClientCertificateRequest = _reflection.GeneratedProtocolMessageType('GenerateGatewayClientCertificateRequest', (_message.Message,), {
'DESCRIPTOR' : _GENERATEGATEWAYCLIENTCERTIFICATEREQUEST,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GenerateGatewayClientCertificateRequest)
})
_sym_db.RegisterMessage(GenerateGatewayClientCertificateRequest)
GenerateGatewayClientCertificateResponse = _reflection.GeneratedProtocolMessageType('GenerateGatewayClientCertificateResponse', (_message.Message,), {
'DESCRIPTOR' : _GENERATEGATEWAYCLIENTCERTIFICATERESPONSE,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GenerateGatewayClientCertificateResponse)
})
_sym_db.RegisterMessage(GenerateGatewayClientCertificateResponse)
GetGatewayMetricsRequest = _reflection.GeneratedProtocolMessageType('GetGatewayMetricsRequest', (_message.Message,), {
'DESCRIPTOR' : _GETGATEWAYMETRICSREQUEST,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GetGatewayMetricsRequest)
})
_sym_db.RegisterMessage(GetGatewayMetricsRequest)
GetGatewayMetricsResponse = _reflection.GeneratedProtocolMessageType('GetGatewayMetricsResponse', (_message.Message,), {
'DESCRIPTOR' : _GETGATEWAYMETRICSRESPONSE,
'__module__' : 'chirpstack_api.api.gateway_pb2'
# @@protoc_insertion_point(class_scope:api.GetGatewayMetricsResponse)
})
_sym_db.RegisterMessage(GetGatewayMetricsResponse)
_GATEWAYSERVICE = DESCRIPTOR.services_by_name['GatewayService']
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chirpstack_api.api.gateway_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,10 +2,9 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: chirpstack-api/api/user.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
@ -19,105 +18,8 @@ from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x63hirpstack-api/api/user.proto\x12\x03\x61pi\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\"T\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08is_admin\x18\x04 \x01(\x08\x12\x11\n\tis_active\x18\x05 \x01(\x08\x12\r\n\x05\x65mail\x18\x06 \x01(\t\x12\x0c\n\x04note\x18\x07 \x01(\t\"\xae\x01\n\x0cUserListItem\x12\n\n\x02id\x18\x01 \x01(\t\x12.\n\ncreated_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\r\n\x05\x65mail\x18\x04 \x01(\t\x12\x10\n\x08is_admin\x18\x05 \x01(\x08\x12\x11\n\tis_active\x18\x06 \x01(\x08\"d\n\nUserTenant\x12\x11\n\ttenant_id\x18\x01 \x01(\t\x12\x10\n\x08is_admin\x18\x02 \x01(\x08\x12\x17\n\x0fis_device_admin\x18\x03 \x01(\x08\x12\x18\n\x10is_gateway_admin\x18\x04 \x01(\x08\"`\n\x11\x43reateUserRequest\x12\x17\n\x04user\x18\x01 \x01(\x0b\x32\t.api.User\x12\x10\n\x08password\x18\x02 \x01(\t\x12 \n\x07tenants\x18\x03 \x03(\x0b\x32\x0f.api.UserTenant\" \n\x12\x43reateUserResponse\x12\n\n\x02id\x18\x01 \x01(\t\"\x1c\n\x0eGetUserRequest\x12\n\n\x02id\x18\x01 \x01(\t\"\x8a\x01\n\x0fGetUserResponse\x12\x17\n\x04user\x18\x01 \x01(\x0b\x32\t.api.User\x12.\n\ncreated_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\",\n\x11UpdateUserRequest\x12\x17\n\x04user\x18\x01 \x01(\x0b\x32\t.api.User\"\x1f\n\x11\x44\x65leteUserRequest\x12\n\n\x02id\x18\x01 \x01(\t\"1\n\x10ListUsersRequest\x12\r\n\x05limit\x18\x01 \x01(\r\x12\x0e\n\x06offset\x18\x02 \x01(\r\"K\n\x11ListUsersResponse\x12\x13\n\x0btotal_count\x18\x01 \x01(\r\x12!\n\x06result\x18\x02 \x03(\x0b\x32\x11.api.UserListItem\">\n\x19UpdateUserPasswordRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t2\x97\x04\n\x0bUserService\x12P\n\x06\x43reate\x12\x16.api.CreateUserRequest\x1a\x17.api.CreateUserResponse\"\x15\x82\xd3\xe4\x93\x02\x0f\"\n/api/users:\x01*\x12I\n\x03Get\x12\x13.api.GetUserRequest\x1a\x14.api.GetUserResponse\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/api/users/{id}\x12Y\n\x06Update\x12\x16.api.UpdateUserRequest\x1a\x16.google.protobuf.Empty\"\x1f\x82\xd3\xe4\x93\x02\x19\x1a\x14/api/users/{user.id}:\x01*\x12Q\n\x06\x44\x65lete\x12\x16.api.DeleteUserRequest\x1a\x16.google.protobuf.Empty\"\x17\x82\xd3\xe4\x93\x02\x11*\x0f/api/users/{id}\x12I\n\x04List\x12\x15.api.ListUsersRequest\x1a\x16.api.ListUsersResponse\"\x12\x82\xd3\xe4\x93\x02\x0c\x12\n/api/users\x12r\n\x0eUpdatePassword\x12\x1e.api.UpdateUserPasswordRequest\x1a\x16.google.protobuf.Empty\"(\x82\xd3\xe4\x93\x02\"\"\x1d/api/users/{user_id}/password:\x01*BP\n\x11io.chirpstack.apiB\tUserProtoP\x01Z.github.com/chirpstack/chirpstack/api/go/v4/apib\x06proto3')
_USER = DESCRIPTOR.message_types_by_name['User']
_USERLISTITEM = DESCRIPTOR.message_types_by_name['UserListItem']
_USERTENANT = DESCRIPTOR.message_types_by_name['UserTenant']
_CREATEUSERREQUEST = DESCRIPTOR.message_types_by_name['CreateUserRequest']
_CREATEUSERRESPONSE = DESCRIPTOR.message_types_by_name['CreateUserResponse']
_GETUSERREQUEST = DESCRIPTOR.message_types_by_name['GetUserRequest']
_GETUSERRESPONSE = DESCRIPTOR.message_types_by_name['GetUserResponse']
_UPDATEUSERREQUEST = DESCRIPTOR.message_types_by_name['UpdateUserRequest']
_DELETEUSERREQUEST = DESCRIPTOR.message_types_by_name['DeleteUserRequest']
_LISTUSERSREQUEST = DESCRIPTOR.message_types_by_name['ListUsersRequest']
_LISTUSERSRESPONSE = DESCRIPTOR.message_types_by_name['ListUsersResponse']
_UPDATEUSERPASSWORDREQUEST = DESCRIPTOR.message_types_by_name['UpdateUserPasswordRequest']
User = _reflection.GeneratedProtocolMessageType('User', (_message.Message,), {
'DESCRIPTOR' : _USER,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.User)
})
_sym_db.RegisterMessage(User)
UserListItem = _reflection.GeneratedProtocolMessageType('UserListItem', (_message.Message,), {
'DESCRIPTOR' : _USERLISTITEM,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.UserListItem)
})
_sym_db.RegisterMessage(UserListItem)
UserTenant = _reflection.GeneratedProtocolMessageType('UserTenant', (_message.Message,), {
'DESCRIPTOR' : _USERTENANT,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.UserTenant)
})
_sym_db.RegisterMessage(UserTenant)
CreateUserRequest = _reflection.GeneratedProtocolMessageType('CreateUserRequest', (_message.Message,), {
'DESCRIPTOR' : _CREATEUSERREQUEST,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.CreateUserRequest)
})
_sym_db.RegisterMessage(CreateUserRequest)
CreateUserResponse = _reflection.GeneratedProtocolMessageType('CreateUserResponse', (_message.Message,), {
'DESCRIPTOR' : _CREATEUSERRESPONSE,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.CreateUserResponse)
})
_sym_db.RegisterMessage(CreateUserResponse)
GetUserRequest = _reflection.GeneratedProtocolMessageType('GetUserRequest', (_message.Message,), {
'DESCRIPTOR' : _GETUSERREQUEST,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.GetUserRequest)
})
_sym_db.RegisterMessage(GetUserRequest)
GetUserResponse = _reflection.GeneratedProtocolMessageType('GetUserResponse', (_message.Message,), {
'DESCRIPTOR' : _GETUSERRESPONSE,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.GetUserResponse)
})
_sym_db.RegisterMessage(GetUserResponse)
UpdateUserRequest = _reflection.GeneratedProtocolMessageType('UpdateUserRequest', (_message.Message,), {
'DESCRIPTOR' : _UPDATEUSERREQUEST,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.UpdateUserRequest)
})
_sym_db.RegisterMessage(UpdateUserRequest)
DeleteUserRequest = _reflection.GeneratedProtocolMessageType('DeleteUserRequest', (_message.Message,), {
'DESCRIPTOR' : _DELETEUSERREQUEST,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.DeleteUserRequest)
})
_sym_db.RegisterMessage(DeleteUserRequest)
ListUsersRequest = _reflection.GeneratedProtocolMessageType('ListUsersRequest', (_message.Message,), {
'DESCRIPTOR' : _LISTUSERSREQUEST,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.ListUsersRequest)
})
_sym_db.RegisterMessage(ListUsersRequest)
ListUsersResponse = _reflection.GeneratedProtocolMessageType('ListUsersResponse', (_message.Message,), {
'DESCRIPTOR' : _LISTUSERSRESPONSE,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.ListUsersResponse)
})
_sym_db.RegisterMessage(ListUsersResponse)
UpdateUserPasswordRequest = _reflection.GeneratedProtocolMessageType('UpdateUserPasswordRequest', (_message.Message,), {
'DESCRIPTOR' : _UPDATEUSERPASSWORDREQUEST,
'__module__' : 'chirpstack_api.api.user_pb2'
# @@protoc_insertion_point(class_scope:api.UpdateUserPasswordRequest)
})
_sym_db.RegisterMessage(UpdateUserPasswordRequest)
_USERSERVICE = DESCRIPTOR.services_by_name['UserService']
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chirpstack_api.api.user_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None

View File

@ -2,11 +2,9 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: chirpstack-api/common/common.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import enum_type_wrapper
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
@ -18,106 +16,8 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"chirpstack-api/common/common.proto\x12\x06\x63ommon\x1a\x1fgoogle/protobuf/timestamp.proto\"{\n\x08Location\x12\x10\n\x08latitude\x18\x01 \x01(\x01\x12\x11\n\tlongitude\x18\x02 \x01(\x01\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x01\x12&\n\x06source\x18\x04 \x01(\x0e\x32\x16.common.LocationSource\x12\x10\n\x08\x61\x63\x63uracy\x18\x05 \x01(\x02\"1\n\x0bKeyEnvelope\x12\x11\n\tkek_label\x18\x01 \x01(\t\x12\x0f\n\x07\x61\x65s_key\x18\x02 \x01(\x0c\"\x91\x01\n\x06Metric\x12\x0c\n\x04name\x18\x01 \x01(\t\x12.\n\ntimestamps\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\x12\'\n\x08\x64\x61tasets\x18\x03 \x03(\x0b\x32\x15.common.MetricDataset\x12 \n\x04kind\x18\x04 \x01(\x0e\x32\x12.common.MetricKind\",\n\rMetricDataset\x12\r\n\x05label\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x03(\x02*,\n\nModulation\x12\x08\n\x04LORA\x10\x00\x12\x07\n\x03\x46SK\x10\x01\x12\x0b\n\x07LR_FHSS\x10\x02*\xaa\x01\n\x06Region\x12\t\n\x05\x45U868\x10\x00\x12\t\n\x05US915\x10\x02\x12\t\n\x05\x43N779\x10\x03\x12\t\n\x05\x45U433\x10\x04\x12\t\n\x05\x41U915\x10\x05\x12\t\n\x05\x43N470\x10\x06\x12\t\n\x05\x41S923\x10\x07\x12\x0b\n\x07\x41S923_2\x10\x0c\x12\x0b\n\x07\x41S923_3\x10\r\x12\x0b\n\x07\x41S923_4\x10\x0e\x12\t\n\x05KR920\x10\x08\x12\t\n\x05IN865\x10\t\x12\t\n\x05RU864\x10\n\x12\x0b\n\x07ISM2400\x10\x0b*\xb3\x01\n\x05MType\x12\x10\n\x0cJOIN_REQUEST\x10\x00\x12\x0f\n\x0bJOIN_ACCEPT\x10\x01\x12\x17\n\x13UNCONFIRMED_DATA_UP\x10\x02\x12\x19\n\x15UNCONFIRMED_DATA_DOWN\x10\x03\x12\x15\n\x11\x43ONFIRMED_DATA_UP\x10\x04\x12\x17\n\x13\x43ONFIRMED_DATA_DOWN\x10\x05\x12\x12\n\x0eREJOIN_REQUEST\x10\x06\x12\x0f\n\x0bPROPRIETARY\x10\x07*~\n\nMacVersion\x12\x11\n\rLORAWAN_1_0_0\x10\x00\x12\x11\n\rLORAWAN_1_0_1\x10\x01\x12\x11\n\rLORAWAN_1_0_2\x10\x02\x12\x11\n\rLORAWAN_1_0_3\x10\x03\x12\x11\n\rLORAWAN_1_0_4\x10\x04\x12\x11\n\rLORAWAN_1_1_0\x10\x05*e\n\x11RegParamsRevision\x12\x05\n\x01\x41\x10\x00\x12\x05\n\x01\x42\x10\x01\x12\x0f\n\x0bRP002_1_0_0\x10\x02\x12\x0f\n\x0bRP002_1_0_1\x10\x03\x12\x0f\n\x0bRP002_1_0_2\x10\x04\x12\x0f\n\x0bRP002_1_0_3\x10\x05*\x8e\x01\n\x0eLocationSource\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03GPS\x10\x01\x12\n\n\x06\x43ONFIG\x10\x02\x12\x15\n\x11GEO_RESOLVER_TDOA\x10\x03\x12\x15\n\x11GEO_RESOLVER_RSSI\x10\x04\x12\x15\n\x11GEO_RESOLVER_GNSS\x10\x05\x12\x15\n\x11GEO_RESOLVER_WIFI\x10\x06*+\n\x0b\x41ggregation\x12\x08\n\x04HOUR\x10\x00\x12\x07\n\x03\x44\x41Y\x10\x01\x12\t\n\x05MONTH\x10\x02*2\n\nMetricKind\x12\x0b\n\x07\x43OUNTER\x10\x00\x12\x0c\n\x08\x41\x42SOLUTE\x10\x01\x12\t\n\x05GAUGE\x10\x02\x42U\n\x11io.chirpstack.apiB\x0b\x43ommonProtoP\x01Z1github.com/chirpstack/chirpstack/api/go/v4/commonb\x06proto3')
_MODULATION = DESCRIPTOR.enum_types_by_name['Modulation']
Modulation = enum_type_wrapper.EnumTypeWrapper(_MODULATION)
_REGION = DESCRIPTOR.enum_types_by_name['Region']
Region = enum_type_wrapper.EnumTypeWrapper(_REGION)
_MTYPE = DESCRIPTOR.enum_types_by_name['MType']
MType = enum_type_wrapper.EnumTypeWrapper(_MTYPE)
_MACVERSION = DESCRIPTOR.enum_types_by_name['MacVersion']
MacVersion = enum_type_wrapper.EnumTypeWrapper(_MACVERSION)
_REGPARAMSREVISION = DESCRIPTOR.enum_types_by_name['RegParamsRevision']
RegParamsRevision = enum_type_wrapper.EnumTypeWrapper(_REGPARAMSREVISION)
_LOCATIONSOURCE = DESCRIPTOR.enum_types_by_name['LocationSource']
LocationSource = enum_type_wrapper.EnumTypeWrapper(_LOCATIONSOURCE)
_AGGREGATION = DESCRIPTOR.enum_types_by_name['Aggregation']
Aggregation = enum_type_wrapper.EnumTypeWrapper(_AGGREGATION)
_METRICKIND = DESCRIPTOR.enum_types_by_name['MetricKind']
MetricKind = enum_type_wrapper.EnumTypeWrapper(_METRICKIND)
LORA = 0
FSK = 1
LR_FHSS = 2
EU868 = 0
US915 = 2
CN779 = 3
EU433 = 4
AU915 = 5
CN470 = 6
AS923 = 7
AS923_2 = 12
AS923_3 = 13
AS923_4 = 14
KR920 = 8
IN865 = 9
RU864 = 10
ISM2400 = 11
JOIN_REQUEST = 0
JOIN_ACCEPT = 1
UNCONFIRMED_DATA_UP = 2
UNCONFIRMED_DATA_DOWN = 3
CONFIRMED_DATA_UP = 4
CONFIRMED_DATA_DOWN = 5
REJOIN_REQUEST = 6
PROPRIETARY = 7
LORAWAN_1_0_0 = 0
LORAWAN_1_0_1 = 1
LORAWAN_1_0_2 = 2
LORAWAN_1_0_3 = 3
LORAWAN_1_0_4 = 4
LORAWAN_1_1_0 = 5
A = 0
B = 1
RP002_1_0_0 = 2
RP002_1_0_1 = 3
RP002_1_0_2 = 4
RP002_1_0_3 = 5
UNKNOWN = 0
GPS = 1
CONFIG = 2
GEO_RESOLVER_TDOA = 3
GEO_RESOLVER_RSSI = 4
GEO_RESOLVER_GNSS = 5
GEO_RESOLVER_WIFI = 6
HOUR = 0
DAY = 1
MONTH = 2
COUNTER = 0
ABSOLUTE = 1
GAUGE = 2
_LOCATION = DESCRIPTOR.message_types_by_name['Location']
_KEYENVELOPE = DESCRIPTOR.message_types_by_name['KeyEnvelope']
_METRIC = DESCRIPTOR.message_types_by_name['Metric']
_METRICDATASET = DESCRIPTOR.message_types_by_name['MetricDataset']
Location = _reflection.GeneratedProtocolMessageType('Location', (_message.Message,), {
'DESCRIPTOR' : _LOCATION,
'__module__' : 'chirpstack_api.common.common_pb2'
# @@protoc_insertion_point(class_scope:common.Location)
})
_sym_db.RegisterMessage(Location)
KeyEnvelope = _reflection.GeneratedProtocolMessageType('KeyEnvelope', (_message.Message,), {
'DESCRIPTOR' : _KEYENVELOPE,
'__module__' : 'chirpstack_api.common.common_pb2'
# @@protoc_insertion_point(class_scope:common.KeyEnvelope)
})
_sym_db.RegisterMessage(KeyEnvelope)
Metric = _reflection.GeneratedProtocolMessageType('Metric', (_message.Message,), {
'DESCRIPTOR' : _METRIC,
'__module__' : 'chirpstack_api.common.common_pb2'
# @@protoc_insertion_point(class_scope:common.Metric)
})
_sym_db.RegisterMessage(Metric)
MetricDataset = _reflection.GeneratedProtocolMessageType('MetricDataset', (_message.Message,), {
'DESCRIPTOR' : _METRICDATASET,
'__module__' : 'chirpstack_api.common.common_pb2'
# @@protoc_insertion_point(class_scope:common.MetricDataset)
})
_sym_db.RegisterMessage(MetricDataset)
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chirpstack_api.common.common_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,10 +2,9 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: chirpstack-api/meta/meta.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
@ -18,24 +17,8 @@ from chirpstack_api.gw import gw_pb2 as chirpstack__api_dot_gw_dot_gw__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x63hirpstack-api/meta/meta.proto\x12\x04meta\x1a\"chirpstack-api/common/common.proto\x1a\x1a\x63hirpstack-api/gw/gw.proto\"\xf0\x01\n\nUplinkMeta\x12\x0f\n\x07\x64\x65v_eui\x18\x01 \x01(\t\x12!\n\x07tx_info\x18\x02 \x01(\x0b\x32\x10.gw.UplinkTxInfo\x12!\n\x07rx_info\x18\x03 \x03(\x0b\x32\x10.gw.UplinkRxInfo\x12\x1e\n\x16phy_payload_byte_count\x18\x04 \x01(\r\x12\x1e\n\x16mac_command_byte_count\x18\x05 \x01(\r\x12&\n\x1e\x61pplication_payload_byte_count\x18\x06 \x01(\r\x12#\n\x0cmessage_type\x18\x07 \x01(\x0e\x32\r.common.MType\"\x81\x02\n\x0c\x44ownlinkMeta\x12\x0f\n\x07\x64\x65v_eui\x18\x01 \x01(\t\x12\x1a\n\x12multicast_group_id\x18\x02 \x01(\t\x12#\n\x07tx_info\x18\x03 \x01(\x0b\x32\x12.gw.DownlinkTxInfo\x12\x1e\n\x16phy_payload_byte_count\x18\x04 \x01(\r\x12\x1e\n\x16mac_command_byte_count\x18\x05 \x01(\r\x12&\n\x1e\x61pplication_payload_byte_count\x18\x06 \x01(\r\x12#\n\x0cmessage_type\x18\x07 \x01(\x0e\x32\r.common.MType\x12\x12\n\ngateway_id\x18\x08 \x01(\tBV\n\x16io.chirpstack.api.metaB\tMetaProtoP\x01Z/github.com/chirpstack/chirpstack/api/go/v4/metab\x06proto3')
_UPLINKMETA = DESCRIPTOR.message_types_by_name['UplinkMeta']
_DOWNLINKMETA = DESCRIPTOR.message_types_by_name['DownlinkMeta']
UplinkMeta = _reflection.GeneratedProtocolMessageType('UplinkMeta', (_message.Message,), {
'DESCRIPTOR' : _UPLINKMETA,
'__module__' : 'chirpstack_api.meta.meta_pb2'
# @@protoc_insertion_point(class_scope:meta.UplinkMeta)
})
_sym_db.RegisterMessage(UplinkMeta)
DownlinkMeta = _reflection.GeneratedProtocolMessageType('DownlinkMeta', (_message.Message,), {
'DESCRIPTOR' : _DOWNLINKMETA,
'__module__' : 'chirpstack_api.meta.meta_pb2'
# @@protoc_insertion_point(class_scope:meta.DownlinkMeta)
})
_sym_db.RegisterMessage(DownlinkMeta)
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chirpstack_api.meta.meta_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None

View File

@ -18,7 +18,7 @@ CLASSIFIERS = [
setup(
name='chirpstack-api',
version = "4.0.1",
version = "4.0.3-test.1",
url='https://github.com/brocaar/chirpstack-api',
author='Orne Brocaar',
author_email='info@brocaar.com',

2
api/rust/Cargo.lock generated vendored
View File

@ -117,7 +117,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chirpstack_api"
version = "4.0.1"
version = "4.0.3-test.1"
dependencies = [
"hex",
"pbjson",

2
api/rust/Cargo.toml vendored
View File

@ -1,7 +1,7 @@
[package]
name = "chirpstack_api"
description = "ChirpStack Protobuf / gRPC API definitions."
version = "4.0.1"
version = "4.0.3-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
license = "MIT"
homepage = "https://www.chirpstack.io"

View File

@ -1,6 +1,6 @@
[package]
name = "backend"
version = "4.0.1"
version = "4.0.3-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
edition = "2018"
publish = false

View File

@ -3,7 +3,7 @@ name = "chirpstack"
description = "ChirpStack is an open-source LoRaWAN(TM) Network Server"
repository = "https://github.com/chirpstack/chirpstack"
homepage="https://www.chirpstack.io/"
version = "4.0.1"
version = "4.0.3-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
edition = "2021"
publish = false
@ -11,7 +11,7 @@ license = "MIT"
[dependencies]
# CLI interface
clap = "3.2"
clap = { version = "4.0", features = ["derive"] }
# Configuration
serde = { version = "1.0", features = ["derive", "rc"] }

View File

@ -4,7 +4,6 @@ use std::time::SystemTime;
use bigdecimal::ToPrimitive;
use chrono::{DateTime, Local, Utc};
use rand::RngCore;
use tonic::{Request, Response, Status};
use uuid::Uuid;
@ -19,7 +18,7 @@ use crate::storage::error::Error;
use crate::storage::{
device, device_keys, device_profile, device_queue, device_session, fields, metrics,
};
use crate::{codec, config};
use crate::{codec, devaddr::get_random_dev_addr};
pub struct Device {
validator: validator::RequestValidator,
@ -547,20 +546,8 @@ impl DeviceService for Device {
&self,
_request: Request<api::GetRandomDevAddrRequest>,
) -> Result<Response<api::GetRandomDevAddrResponse>, Status> {
let conf = config::get();
let mut dev_addr: [u8; 4] = [0; 4];
rand::thread_rng().fill_bytes(&mut dev_addr);
#[cfg(test)]
{
dev_addr = [1, 2, 3, 4];
}
let mut dev_addr = DevAddr::from_be_bytes(dev_addr);
dev_addr.set_addr_prefix(&conf.network.net_id);
Ok(Response::new(api::GetRandomDevAddrResponse {
dev_addr: dev_addr.to_string(),
dev_addr: get_random_dev_addr().to_string(),
}))
}
@ -1347,7 +1334,7 @@ pub mod test {
.unwrap();
let dev_addr = DevAddr::from_str(&get_random_dev_addr_resp.get_ref().dev_addr).unwrap();
let mut dev_addr_copy = dev_addr.clone();
dev_addr_copy.set_addr_prefix(&NetID::from_str("000000").unwrap());
dev_addr_copy.set_dev_addr_prefix(NetID::from_str("000000").unwrap().dev_addr_prefix());
assert_eq!(dev_addr, dev_addr_copy);
// enqueue

View File

@ -675,6 +675,7 @@ impl InternalService for Internal {
// detect client disconnect
_ = close_rx.recv() => {
debug!("Client disconnected");
redis_rx.close();
break;
}
// detect get_frame_logs function return

View File

@ -117,6 +117,26 @@ pub fn run() {
# Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203).
net_id="{{ network.net_id }}"
# DevAddr prefix(es).
#
# This makes it possible to configure one or multiple sub-ranges within
# the configured NetID. If left blank, then the complete DevAddr space
# provided by the configured NetID will be used.
# If multiple prefixes are configured, a random prefix will be chosen when
# generating a DevAddr.
#
# Example configuration:
# dev_addr_prefixes=["0000ff00/24"]
#
# This example configures the DevAddr range to 0000ff00 - 0000ffff.
# The /24 means that the 24MSB of the prefix will be used, meaning that the
# 8LSB will be used as address space.
dev_addr_prefixes=[
{{#each network.dev_addr_prefixes}}
"{{this}}",
{{/each}}
]
# Enabled regions.
#
# Multiple regions can be enabled simultaneously. Each region must match
@ -355,7 +375,7 @@ pub fn run() {
# Certificate lifetime.
#
# This defines how long (after generating) the certificate remains valid.
client_cert_lifetime="{{ integration.mqtt.client_cert_lifetime }}"
client_cert_lifetime="{{ integration.mqtt.client.client_cert_lifetime }}"
# PostgreSQL integration configuration.

View File

@ -14,9 +14,15 @@ fn _rquickjs_to_struct_val(val: &rquickjs::Value) -> Option<pbjson_types::value:
rquickjs::Type::Int => Some(pbjson_types::value::Kind::NumberValue(
val.as_int().unwrap().into(),
)),
rquickjs::Type::Float => Some(pbjson_types::value::Kind::NumberValue(
val.as_float().unwrap(),
)),
rquickjs::Type::Float => {
let v = val.as_float().unwrap();
if v.is_nan() {
// Avoid Cannot serialize NaN as google.protobuf.Value.number_value error.
None
} else {
Some(pbjson_types::value::Kind::NumberValue(v))
}
}
rquickjs::Type::String => Some(pbjson_types::value::Kind::StringValue(
val.as_string().unwrap().to_string().unwrap(),
)),

View File

@ -7,7 +7,7 @@ use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use lrwn::region::CommonName;
use lrwn::{AES128Key, NetID, EUI64};
use lrwn::{AES128Key, DevAddrPrefix, NetID, EUI64};
lazy_static! {
static ref CONFIG: Mutex<Arc<Configuration>> = Mutex::new(Arc::new(Default::default()));
@ -150,6 +150,7 @@ impl Default for Gateway {
#[serde(default)]
pub struct Network {
pub net_id: NetID,
pub dev_addr_prefixes: Vec<DevAddrPrefix>,
pub enabled_regions: Vec<String>,
#[serde(with = "humantime_serde")]
pub device_session_ttl: Duration,
@ -164,6 +165,7 @@ impl Default for Network {
fn default() -> Self {
Network {
net_id: NetID::from_be_bytes([0x00, 0x00, 0x00]),
dev_addr_prefixes: vec![],
enabled_regions: vec!["eu868".into()],
device_session_ttl: Duration::from_secs(60 * 60 * 24 * 31),
deduplication_delay: Duration::from_millis(200),

33
chirpstack/src/devaddr.rs Normal file
View File

@ -0,0 +1,33 @@
use rand::seq::SliceRandom;
use rand::RngCore;
use crate::config;
use lrwn::DevAddr;
pub fn get_random_dev_addr() -> DevAddr {
let conf = config::get();
let mut rng = rand::thread_rng();
// Get configured DevAddr prefixes.
let prefixes = if conf.network.dev_addr_prefixes.is_empty() {
vec![conf.network.net_id.dev_addr_prefix()]
} else {
conf.network.dev_addr_prefixes.clone()
};
// Pick a random one (in case multiple prefixes are configured).
let prefix = *prefixes.choose(&mut rng).unwrap();
// Generate random DevAddr.
let mut dev_addr: [u8; 4] = [0; 4];
rng.fill_bytes(&mut dev_addr);
#[cfg(test)]
{
dev_addr = [1, 2, 3, 4];
}
let mut dev_addr = DevAddr::from_be_bytes(dev_addr);
// Set DevAddr prefix.
dev_addr.set_dev_addr_prefix(prefix);
dev_addr
}

View File

@ -96,210 +96,225 @@ pub async fn get_event_logs(
for stream_id in &stream_key.ids {
last_id = stream_id.id.clone();
for (k, v) in &stream_id.map {
match k.as_ref() {
"up" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::UplinkEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("DR".to_string(), format!("{}", pl.dr)),
("FPort".to_string(), format!("{}", pl.f_port)),
("Data".to_string(), hex::encode(&pl.data)),
]
.iter()
.cloned()
.collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"join" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::JoinEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [("DevAddr".to_string(), pl.dev_addr)]
let res = || -> Result<()> {
match k.as_ref() {
"up" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::UplinkEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("DR".to_string(), format!("{}", pl.dr)),
("FPort".to_string(), format!("{}", pl.f_port)),
("Data".to_string(), hex::encode(&pl.data)),
]
.iter()
.cloned()
.collect(),
};
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
}
"ack" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::AckEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [].iter().cloned().collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"txack" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::TxAckEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [].iter().cloned().collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"status" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::StatusEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("Margin".into(), format!("{}", pl.margin)),
(
"Battery level".into(),
format!("{:.0}%", pl.battery_level),
),
(
"Battery level unavailable".into(),
format!("{}", pl.battery_level_unavailable),
),
(
"External power source".into(),
format!("{}", pl.external_power_source),
),
]
.iter()
.cloned()
.collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"log" => {
trace!(key = %k, id =%last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::LogEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("Level".into(), pl.level().into()),
("Code".into(), pl.code().into()),
]
.iter()
.cloned()
.collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"location" => {
trace!(key = %k, id=%last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::LocationEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [].iter().cloned().collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"integration" => {
trace!(key = %k, id=%last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl =
integration::IntegrationEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
"join" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::JoinEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("Integration".into(), pl.integration_name.clone()),
("Event".into(), pl.event_type.clone()),
]
.iter()
.cloned()
.collect(),
};
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [("DevAddr".to_string(), pl.dev_addr)]
.iter()
.cloned()
.collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"ack" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::AckEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [].iter().cloned().collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"txack" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::TxAckEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [].iter().cloned().collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"status" => {
trace!(key = %k, id = %last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::StatusEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("Margin".into(), format!("{}", pl.margin)),
(
"Battery level".into(),
format!("{:.0}%", pl.battery_level),
),
(
"Battery level unavailable".into(),
format!("{}", pl.battery_level_unavailable),
),
(
"External power source".into(),
format!("{}", pl.external_power_source),
),
]
.iter()
.cloned()
.collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"log" => {
trace!(key = %k, id =%last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::LogEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("Level".into(), pl.level().into()),
("Code".into(), pl.code().into()),
]
.iter()
.cloned()
.collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"location" => {
trace!(key = %k, id=%last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl = integration::LocationEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [].iter().cloned().collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
"integration" => {
trace!(key = %k, id=%last_id, "Event-log received from stream");
if let redis::Value::Data(b) = v {
let pl =
integration::IntegrationEvent::decode(&mut Cursor::new(b))?;
let pl = api::LogItem {
id: stream_id.id.clone(),
time: pl.time.as_ref().map(|v| prost_types::Timestamp{
seconds: v.seconds,
nanos: v.nanos,
}),
description: k.clone(),
body: serde_json::to_string(&pl)?,
properties: [
("Integration".into(), pl.integration_name.clone()),
("Event".into(), pl.event_type.clone()),
]
.iter()
.cloned()
.collect(),
};
if channel.blocking_send(pl).is_err() {
return Err(anyhow!("Channel send error"));
}
}
}
_ => {
error!(key = %k, "Unexpected key in in event-log stream");
}
}
_ => {
error!(key = %k, "Unexpected key in in event-log stream");
Ok(())
}();
if let Err(e) = res {
// Return in case of channel error, in any other case we just log
// the error.
if e.downcast_ref::<mpsc::error::SendError<api::LogItem>>().is_some() {
return Err(e);
}
error!(key = %k, error = %e, "Parsing frame-log error");
}
}
}

View File

@ -9,7 +9,7 @@ use redis::streams::StreamReadReply;
use serde_json::json;
use tokio::sync::mpsc;
use tokio::task;
use tracing::{error, trace};
use tracing::{debug, error, trace};
use lrwn::EUI64;
@ -68,7 +68,7 @@ pub async fn log_uplink_for_gateways(ufl: &api::UplinkFrameLog) -> Result<()> {
// global gateway stream
if conf.monitoring.gateway_frame_log_max_history > 0 {
let key = redis_key("gw:stream::frame".to_string());
let key = redis_key("gw:stream:frame".to_string());
redis::cmd("XADD")
.arg(&key)
.arg("MAXLEN")
@ -256,6 +256,11 @@ pub async fn get_frame_logs(
let mut c = get_redis_conn()?;
loop {
if channel.is_closed() {
debug!("Channel has been closed, returning");
return Ok(());
}
let srr: StreamReadReply = redis::cmd("XREAD")
.arg("COUNT")
.arg(count)
@ -362,6 +367,7 @@ pub async fn get_frame_logs(
// check every 1 second if there are new messages, which should be sufficient.
sleep(Duration::from_secs(1));
}
}
}).await?
}

View File

@ -113,7 +113,7 @@ impl<'a> Integration<'a> {
if !conf.ca_cert.is_empty() {
ssl_opts_b
.ca_path(&conf.ca_cert)
.trust_store(&conf.ca_cert)
.context("Failed to set gateway ca_cert")?;
}

View File

@ -12,7 +12,7 @@ use std::process;
use std::str::FromStr;
use anyhow::Result;
use clap::{App, Arg};
use clap::{Parser, Subcommand};
use tracing::Level;
use tracing_subscriber::{filter, prelude::*};
@ -25,6 +25,7 @@ mod certificate;
mod cmd;
mod codec;
mod config;
mod devaddr;
mod downlink;
mod eventlog;
mod framelog;
@ -41,57 +42,41 @@ mod storage;
mod test;
mod uplink;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Path to configuration directory
#[arg(short, long, value_name = "DIR")]
config: String,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
/// Print the configuration template
Configfile {},
/// Print the device-session for debugging
PrintDs {
/// Device EUI
#[arg(long, value_name = "DEV_EUI")]
dev_eui: String,
},
/// Import TheThingsNetwork LoRaWAN devices repository
ImportTtnLorawanDevices {
/// Path to repository root.
#[arg(short, long, value_name = "DIR")]
dir: String,
},
}
#[tokio::main]
async fn main() -> Result<()> {
// read CLI
let matches = App::new("chirpstack")
.version(env!("CARGO_PKG_VERSION"))
.author("Orne Brocaar <info@brocaar.com>")
.about("ChirpStack open-source LoRaWAN network-server")
.arg(
Arg::with_name("config-dir")
.required(true)
.short('c')
.long("config-dir")
.value_name("DIR")
.multiple(false)
.number_of_values(1)
.help("Path to configuration directory")
.takes_value(true),
)
.subcommand(App::new("configfile").about("Print the configuration template"))
.subcommand(
App::new("print-ds")
.about("Print the device-session for debugging")
.arg(
Arg::with_name("dev-eui")
.required(true)
.long("dev-eui")
.value_name("DEV_EUI")
.multiple(false)
.help("Device EUI")
.takes_value(true),
),
)
.subcommand(
App::new("import-ttn-lorawan-devices")
.about("Import TheThingsNetwork LoRaWAN devices repository")
.arg(
Arg::with_name("dir")
.required(true)
.short('d')
.long("dir")
.value_name("DIR")
.multiple(false)
.number_of_values(1)
.help("Path to repository root")
.takes_value(true),
),
)
.get_matches();
let config_dir = matches.get_one::<String>("config-dir").unwrap();
config::load(Path::new(&config_dir))?;
let cli = Cli::parse();
config::load(Path::new(&cli.config))?;
let conf = config::get();
let filter = filter::Targets::new().with_targets(vec![
@ -105,22 +90,19 @@ async fn main() -> Result<()> {
.with(filter)
.init();
if matches.subcommand_matches("configfile").is_some() {
if let Some(Commands::Configfile {}) = &cli.command {
cmd::configfile::run();
process::exit(0);
}
if let Some(v) = matches.subcommand_matches("print-ds") {
let dev_eui = v.get_one::<String>("dev-eui").unwrap();
if let Some(Commands::PrintDs { dev_eui }) = &cli.command {
let dev_eui = EUI64::from_str(dev_eui).unwrap();
cmd::print_ds::run(&dev_eui).await.unwrap();
process::exit(0);
}
if let Some(v) = matches.subcommand_matches("import-ttn-lorawan-devices") {
let dir = v.get_one::<String>("dir").unwrap();
cmd::import_ttn_lorawan_devices::run(Path::new(dir))
if let Some(Commands::ImportTtnLorawanDevices { dir }) = &cli.command {
cmd::import_ttn_lorawan_devices::run(Path::new(&dir))
.await
.unwrap();
process::exit(0);

View File

@ -86,7 +86,9 @@ async fn test_fns_uplink() {
fhdr: lrwn::FHDR {
devaddr: {
let mut d = lrwn::DevAddr::from_be_bytes([0, 0, 0, 0]);
d.set_addr_prefix(&lrwn::NetID::from_str("000505").unwrap());
d.set_dev_addr_prefix(
lrwn::NetID::from_str("000505").unwrap().dev_addr_prefix(),
);
d
},
f_ctrl: Default::default(),
@ -232,7 +234,7 @@ async fn test_sns_uplink() {
.unwrap();
let mut dev_addr = lrwn::DevAddr::from_be_bytes([0, 0, 0, 0]);
dev_addr.set_addr_prefix(&lrwn::NetID::from_str("000505").unwrap());
dev_addr.set_dev_addr_prefix(lrwn::NetID::from_str("000505").unwrap().dev_addr_prefix());
let ds = internal::DeviceSession {
dev_eui: vec![2, 2, 3, 4, 5, 6, 7, 8],
@ -428,7 +430,7 @@ async fn test_sns_dev_not_found() {
roaming::setup().unwrap();
let mut dev_addr = lrwn::DevAddr::from_be_bytes([0, 0, 0, 0]);
dev_addr.set_addr_prefix(&lrwn::NetID::from_str("000505").unwrap());
dev_addr.set_dev_addr_prefix(lrwn::NetID::from_str("000505").unwrap().dev_addr_prefix());
let data_phy = lrwn::PhyPayload {
mhdr: lrwn::MHDR {

View File

@ -3,7 +3,6 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use chrono::{DateTime, Local, Utc};
use rand::RngCore;
use tracing::{error, info, span, trace, Instrument, Level};
use lrwn::{
@ -22,7 +21,9 @@ use crate::storage::{
application, device, device_keys, device_profile, device_queue, error::Error as StorageError,
metrics, tenant,
};
use crate::{config, downlink, framelog, integration, metalog, region};
use crate::{
config, devaddr::get_random_dev_addr, downlink, framelog, integration, metalog, region,
};
use chirpstack_api::{api, common, integration as integration_pb, internal, meta};
pub struct JoinRequest {
@ -349,21 +350,7 @@ impl JoinRequest {
}
fn get_random_dev_addr(&mut self) -> Result<()> {
let conf = config::get();
let mut dev_addr: [u8; 4] = [0; 4];
rand::thread_rng().fill_bytes(&mut dev_addr);
#[cfg(test)]
{
dev_addr = [1, 2, 3, 4];
}
let mut dev_addr = DevAddr::from_be_bytes(dev_addr);
dev_addr.set_addr_prefix(&conf.network.net_id);
self.dev_addr = Some(dev_addr);
self.dev_addr = Some(get_random_dev_addr());
Ok(())
}

View File

@ -2,7 +2,6 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use chrono::{DateTime, Local, Utc};
use rand::RngCore;
use tracing::{span, trace, Instrument, Level};
use super::{helpers, UplinkFrameSet};
@ -12,7 +11,7 @@ use crate::storage::{
application, device, device_keys, device_profile, device_queue, device_session,
error::Error as StorageError, metrics, tenant,
};
use crate::{config, integration, metalog, region};
use crate::{config, devaddr::get_random_dev_addr, integration, metalog, region};
use backend::{PRStartAnsPayload, PRStartReqPayload};
use chirpstack_api::{common, integration as integration_pb, internal, meta};
use lrwn::{keys, AES128Key, DevAddr, NetID};
@ -203,21 +202,7 @@ impl JoinRequest {
}
fn get_random_dev_addr(&mut self) -> Result<()> {
let conf = config::get();
let mut dev_addr: [u8; 4] = [0; 4];
rand::thread_rng().fill_bytes(&mut dev_addr);
#[cfg(test)]
{
dev_addr = [1, 2, 3, 4];
}
let mut dev_addr = DevAddr::from_be_bytes(dev_addr);
dev_addr.set_addr_prefix(&conf.network.net_id);
self.dev_addr = Some(dev_addr);
self.dev_addr = Some(get_random_dev_addr());
Ok(())
}

1
examples/frame_log/go/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
frame-log

View File

@ -0,0 +1,20 @@
module frame-log
go 1.18
require (
github.com/chirpstack/chirpstack/api/go/v4 v4.0.2
github.com/go-redis/redis/v8 v8.11.5
google.golang.org/protobuf v1.28.1
)
require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/golang/protobuf v1.5.2 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
google.golang.org/grpc v1.45.0 // indirect
)

View File

@ -0,0 +1,145 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chirpstack/chirpstack/api/go/v4 v4.0.2 h1:qyblQmhC66zlKFoM5gj9TjHpvCNBMZ+qt11EEpBAb6U=
github.com/chirpstack/chirpstack/api/go/v4 v4.0.2/go.mod h1:KBW7imf70O9ifrMmoFH8+dn0+MUFS1PdC5shXH7W3dI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -0,0 +1,74 @@
package main
import (
"context"
"flag"
"fmt"
"log"
"github.com/chirpstack/chirpstack/api/go/v4/api"
"github.com/go-redis/redis/v8"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
)
var (
server string
key string
)
func init() {
flag.StringVar(&server, "server", "localhost:6379", "Redis hostname:port")
flag.StringVar(&key, "key", "gw:stream:frame", "Redis Streams key to read from")
flag.Parse()
}
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: server,
})
ctx := context.Background()
lastID := "0"
for {
resp, err := rdb.XRead(ctx, &redis.XReadArgs{
Streams: []string{key, lastID},
Count: 10,
Block: 0,
}).Result()
if err != nil {
log.Fatal(err)
}
if len(resp) != 1 {
log.Fatal("Exaclty one stream response is expected")
}
for _, msg := range resp[0].Messages {
lastID = msg.ID
if b, ok := msg.Values["up"].(string); ok {
var pl api.UplinkFrameLog
if err := proto.Unmarshal([]byte(b), &pl); err != nil {
log.Fatal(err)
}
fmt.Println("=== UP ===")
fmt.Println(protojson.Format(&pl))
fmt.Println("==========")
}
if b, ok := msg.Values["down"].(string); ok {
var pl api.DownlinkFrameLog
if err := proto.Unmarshal([]byte(b), &pl); err != nil {
log.Fatal(err)
}
fmt.Println("=== DOWN ===")
fmt.Println(protojson.Format(&pl))
fmt.Println("============")
}
}
}
}

View File

@ -3,7 +3,7 @@ name = "lrwn"
description = "Library for encoding / decoding LoRaWAN frames."
homepage = "https://www.chirpstack.io"
license = "MIT"
version = "4.0.1"
version = "4.0.3-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
edition = "2018"
repository = "https://github.com/chirpstack/chirpstack"

View File

@ -2,11 +2,97 @@ use std::fmt;
use std::str::FromStr;
use anyhow::Result;
use serde::{Serialize, Serializer};
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::netid::NetID;
use crate::Error;
#[derive(PartialEq, Eq, Copy, Clone, Default)]
pub struct DevAddrPrefix([u8; 4], u32);
impl DevAddrPrefix {
pub fn new(prefix: [u8; 4], size: u32) -> Self {
DevAddrPrefix(prefix, size)
}
fn prefix(&self) -> [u8; 4] {
self.0
}
fn size(&self) -> u32 {
self.1
}
}
impl fmt::Display for DevAddrPrefix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}/{}", hex::encode(&self.0), self.1)
}
}
impl fmt::Debug for DevAddrPrefix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}/{}", hex::encode(&self.0), self.1)
}
}
impl FromStr for DevAddrPrefix {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_string();
let parts: Vec<&str> = s.split("/").collect();
if parts.len() != 2 {
return Err(Error::DevAddrPrefixFormat);
}
if parts[0].len() != 8 {
return Err(Error::DevAddrPrefixFormat);
}
let mut mask: [u8; 4] = [0; 4];
hex::decode_to_slice(&parts[0], &mut mask)?;
let size: u32 = parts[1].parse().map_err(|_| Error::DevAddrPrefixFormat)?;
Ok(DevAddrPrefix(mask, size))
}
}
impl Serialize for DevAddrPrefix {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for DevAddrPrefix {
fn deserialize<D>(deserialize: D) -> Result<DevAddrPrefix, D::Error>
where
D: Deserializer<'de>,
{
deserialize.deserialize_str(DevAddrPrefixVisitor)
}
}
struct DevAddrPrefixVisitor;
impl<'de> Visitor<'de> for DevAddrPrefixVisitor {
type Value = DevAddrPrefix;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("A DevAddrPrefix in the format 00000000/0 is expected")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
DevAddrPrefix::from_str(value).map_err(|e| E::custom(format!("{}", e)))
}
}
#[derive(PartialEq, Copy, Clone, AsExpression, FromSqlRow, Default)]
#[diesel(sql_type = diesel::sql_types::Binary)]
pub struct DevAddr([u8; 4]);
@ -54,7 +140,7 @@ impl DevAddr {
pub fn is_net_id(&self, net_id: NetID) -> bool {
let mut dev_addr = *self;
dev_addr.set_addr_prefix(&net_id);
dev_addr.set_dev_addr_prefix(net_id.dev_addr_prefix());
*self == dev_addr
}
@ -83,18 +169,18 @@ impl DevAddr {
}
}
pub fn set_addr_prefix(&mut self, netid: &NetID) {
match netid.netid_type() {
0 => self.set_set_addr_prefix(1, 6, netid),
1 => self.set_set_addr_prefix(2, 6, netid),
2 => self.set_set_addr_prefix(3, 9, netid),
3 => self.set_set_addr_prefix(4, 11, netid),
4 => self.set_set_addr_prefix(5, 12, netid),
5 => self.set_set_addr_prefix(6, 13, netid),
6 => self.set_set_addr_prefix(7, 15, netid),
7 => self.set_set_addr_prefix(8, 17, netid),
_ => {}
}
pub fn set_dev_addr_prefix(&mut self, prefix: DevAddrPrefix) {
// convert devaddr to u32
let mut devaddr = u32::from_be_bytes(self.0);
// clean the prefix bits
let mask = u32::MAX; // all u32 bits to 1
devaddr &= !(mask << (32 - prefix.size()));
// set the prefix
devaddr |= u32::from_be_bytes(prefix.prefix());
self.0 = devaddr.to_be_bytes();
}
fn get_nwkid(&self, prefix_length: u32, nwkid_bits: u32) -> Vec<u8> {
@ -117,31 +203,6 @@ impl DevAddr {
out[4 - blen..].to_vec()
}
fn set_set_addr_prefix(&mut self, prefix_length: u32, nwkid_bits: u32, netid: &NetID) {
// convert devaddr to u32
let mut devaddr = u32::from_be_bytes(self.0);
// clear the bits for the prefix and NwkID
let mask = u32::MAX; // all u32 bits to 1
devaddr &= !(mask << (32 - prefix_length - nwkid_bits));
// set the type prefix
let prefix: u32 = 254 << (32 - prefix_length);
let mut devaddr = devaddr | prefix;
// set the NwkID
let mut netid_bytes: [u8; 4] = [0; 4];
let netid_id = netid.id();
netid_bytes[4 - netid_id.len()..].clone_from_slice(&netid_id);
let mut nwkid = u32::from_be_bytes(netid_bytes);
nwkid <<= 32 - nwkid_bits; // truncate the MSB of the NetID ID field
nwkid >>= prefix_length; // shift base for the prefix MSB
devaddr |= nwkid;
self.0 = devaddr.to_be_bytes();
}
}
impl fmt::Display for DevAddr {
@ -237,42 +298,49 @@ mod tests {
}
#[test]
fn test_to_le_bytes() {
fn test_dev_addr_prefix() {
let p = DevAddrPrefix::from_str("01000000/8").unwrap();
assert_eq!(DevAddrPrefix::new([1, 0, 0, 0], 8), p);
assert_eq!("01000000/8", p.to_string());
}
#[test]
fn test_dev_addr_to_le_bytes() {
for tst in tests() {
assert_eq!(tst.bytes, tst.devaddr.to_le_bytes());
}
}
#[test]
fn test_from_le_bytes() {
fn test_dev_addr_from_le_bytes() {
for tst in tests() {
assert_eq!(tst.devaddr, DevAddr::from_le_bytes(tst.bytes));
}
}
#[test]
fn test_netid_type() {
fn test_dev_addr_netid_type() {
for tst in tests() {
assert_eq!(tst.netid_type, tst.devaddr.netid_type());
}
}
#[test]
fn test_nwkid() {
fn test_dev_addr_nwkid() {
for tst in tests() {
assert_eq!(tst.nwkid, tst.devaddr.nwkid());
}
}
#[test]
fn test_string() {
fn test_dev_addr_string() {
for tst in tests() {
assert_eq!(tst.string, tst.devaddr.to_string());
}
}
#[test]
fn test_set_addr_prefix() {
fn test_dev_addr_set_addr_prefix() {
let tests = vec![
SetAddrPrefixTest {
devaddr: DevAddr::from_be_bytes([0xff, 0xff, 0xff, 0xff]),
@ -288,7 +356,7 @@ mod tests {
for tst in tests {
let mut devaddr = tst.devaddr.clone();
devaddr.set_addr_prefix(&tst.netid);
devaddr.set_dev_addr_prefix(tst.netid.dev_addr_prefix());
assert_eq!(tst.expected_devaddr, devaddr);
}
}

View File

@ -14,6 +14,9 @@ pub enum Error {
#[error("DevAddr expects exactly 4 bytes")]
DevAddrLength,
#[error("DevAddrPrefix must be in the form 00000000/0")]
DevAddrPrefixFormat,
#[error(transparent)]
FromHexError(#[from] hex::FromHexError),
}

View File

@ -5,6 +5,7 @@ use anyhow::Result;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::devaddr::DevAddrPrefix;
use crate::Error;
#[derive(Default, PartialEq, Clone, Copy, Hash, Eq)]
@ -74,6 +75,38 @@ impl NetID {
out[4 - blen..].to_vec()
}
pub fn dev_addr_prefix(&self) -> DevAddrPrefix {
match self.netid_type() {
0 => self.get_dev_addr_prefix(1, 6),
1 => self.get_dev_addr_prefix(2, 6),
2 => self.get_dev_addr_prefix(3, 9),
3 => self.get_dev_addr_prefix(4, 11),
4 => self.get_dev_addr_prefix(5, 12),
5 => self.get_dev_addr_prefix(6, 13),
6 => self.get_dev_addr_prefix(7, 15),
7 => self.get_dev_addr_prefix(8, 17),
_ => panic!("netid_type bug"),
}
}
fn get_dev_addr_prefix(&self, prefix_length: u32, nwkid_bits: u32) -> DevAddrPrefix {
// type prefix
let mut prefix: u32 = 254 << (32 - prefix_length);
// NwkID prefix
let mut netid_bytes: [u8; 4] = [0; 4];
let netid_id = self.id();
netid_bytes[4 - netid_id.len()..].clone_from_slice(&netid_id);
let mut nwkid = u32::from_be_bytes(netid_bytes);
nwkid <<= 32 - nwkid_bits; // truncate the MSB of the NetID ID field
nwkid >>= prefix_length; // shift base for the prefix MSB
// merge type prefix with nwkid.
prefix |= nwkid;
DevAddrPrefix::new(prefix.to_be_bytes(), prefix_length + nwkid_bits)
}
}
impl fmt::Display for NetID {
@ -144,6 +177,7 @@ mod tests {
id: Vec<u8>,
bytes: [u8; 3],
string: String,
dev_addr_prefix: DevAddrPrefix,
}
fn tests() -> Vec<Test> {
@ -154,6 +188,7 @@ mod tests {
id: vec![0x2d],
bytes: [0x6d, 0x00, 0x00],
string: "00006d".into(),
dev_addr_prefix: DevAddrPrefix::new([0x5a, 0x00, 0x00, 0x00], 7),
},
Test {
netid: NetID::from_be_bytes([0x20, 0x00, 0x6d]),
@ -161,6 +196,7 @@ mod tests {
id: vec![0x2d],
bytes: [0x6d, 0x00, 0x20],
string: "20006d".into(),
dev_addr_prefix: DevAddrPrefix::new([0xad, 0x00, 0x00, 0x00], 8),
},
Test {
netid: NetID::from_be_bytes([0x40, 0x03, 0x6d]),
@ -168,6 +204,7 @@ mod tests {
id: vec![0x01, 0x6d],
bytes: [0x6d, 0x03, 0x40],
string: "40036d".into(),
dev_addr_prefix: DevAddrPrefix::new([0xd6, 0xd0, 0x00, 0x00], 12),
},
Test {
netid: NetID::from_be_bytes([0x76, 0xdb, 0x6d]),
@ -175,6 +212,7 @@ mod tests {
id: vec![0x16, 0xdb, 0x6d],
bytes: [0x6d, 0xdb, 0x76],
string: "76db6d".into(),
dev_addr_prefix: DevAddrPrefix::new([0xe6, 0xda, 0x00, 0x00], 15),
},
Test {
netid: NetID::from_be_bytes([0x96, 0xdb, 0x6d]),
@ -182,6 +220,7 @@ mod tests {
id: vec![0x16, 0xdb, 0x6d],
bytes: [0x6d, 0xdb, 0x96],
string: "96db6d".into(),
dev_addr_prefix: DevAddrPrefix::new([0xf5, 0xb6, 0x80, 0x00], 17),
},
Test {
netid: NetID::from_be_bytes([0xb6, 0xdb, 0x6d]),
@ -189,6 +228,7 @@ mod tests {
id: vec![0x16, 0xdb, 0x6d],
bytes: [0x6d, 0xdb, 0xb6],
string: "b6db6d".into(),
dev_addr_prefix: DevAddrPrefix::new([0xfb, 0x6d, 0xa0, 0x00], 19),
},
Test {
netid: NetID::from_be_bytes([0xd6, 0xdb, 0x6d]),
@ -196,6 +236,7 @@ mod tests {
id: vec![0x16, 0xdb, 0x6d],
bytes: [0x6d, 0xdb, 0xd6],
string: "d6db6d".into(),
dev_addr_prefix: DevAddrPrefix::new([0xfd, 0x6d, 0xb4, 00], 22),
},
Test {
netid: NetID::from_be_bytes([0xf6, 0xdb, 0x6d]),
@ -203,6 +244,7 @@ mod tests {
id: vec![0x16, 0xdb, 0x6d],
bytes: [0x6d, 0xdb, 0xf6],
string: "f6db6d".into(),
dev_addr_prefix: DevAddrPrefix::new([0xfe, 0x6d, 0xb6, 0x80], 25),
},
]
}
@ -248,4 +290,11 @@ mod tests {
assert_eq!(tst.netid, NetID::from_str(&tst.string).unwrap());
}
}
#[test]
fn test_dev_addr_prefix() {
for tst in tests() {
assert_eq!(tst.dev_addr_prefix, tst.netid.dev_addr_prefix());
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "chirpstack-ui",
"version": "4.0.1",
"version": "4.0.3-test.1",
"private": true,
"dependencies": {
"@ant-design/colors": "^6.0.0",

View File

@ -1881,7 +1881,7 @@
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@chirpstack/chirpstack-api-grpc-web@file:../api/grpc-web":
version "4.0.1"
version "4.0.3-test.1"
dependencies:
"@types/google-protobuf" "^3.15.2"
google-protobuf "^3.17.3"