[{"content":"Background In previous posts we presented a Prometheus exporter to monitor for monitoring TheThingsNetwork gateways. The exporter can directly be executed in a terminal. However, to use it productively it should run in the background as a service. This article demonstrates how this can be achieved using the system and service manager systemd on Linux systems.\nPreparation The first step is to prepare the environment where the Prometheus exporter is installed. Throughout this article we will use the directory /usr/local/bin/prometheus-ttn-exporter. However, any other directory in the local file system is also possible.\nExecuting the exporter as root is possible, but not ideal. To reduce the privileges as much as possible, it is a better idea to create a system user and group. In our example the user and group is called ttn. We need to ensure that the directory as well as all contained files are owned by the ttn user and group.\nInside the directory we need to place the files ttn_gateway_exporter.py and requirements.txt both as provided in the Github Repository. To isolate the the exporter and its dependencies from the rest of the system, we will use a Python virtual environment (venv). Please note, that with this approach updates are not automatically installed when updating the rest of the system. You must ensure to update the Python venv on your own. The venv can be prepared by executing the following commands as the ttn user.\nvirtualenv --python=python3 venv source venv/bin/activate pip install -r requirements.txt deactivate With this the environment is prepared and the systemd service can be created.\nSystemd Systemd services are defined in text files. A common location for these service files is the directory /etc/systemd/system/. For our example we will create the service file /etc/systemd/system/ttn.service. The minimal content of this file is as follows.\n[Unit] Description=ttn prometheus exporter Requires=network-online.target After=network-online.target [Service] User=ttn Group=ttn ExecStart=/usr/local/bin/prometheus-ttn-exporter/venv/bin/python /usr/local/bin/prometheus-ttn-exporter/ttn_gateway_exporter.py --listen :9715 --key API_KEY [Install] WantedBy=multi-user.target The downside of this minimal example is that the TheThingsNetwork API key is directly stored in the system service file. So every user who is allowed to read the service file can access the API key. Depending on your deployment scenario this might be sufficient. If not other options would be to store the API key directly in the exporter directory and restrict the file access appropriately.\nThe last step is to reload the available systemd service files and start the new ttn service by executing:\nsystemctl daemon-reload systemctl start ttn.service You can now verify that the Prometheus exporter is running by opening http://localhost:9715 in a browser.\n","permalink":"https://www.cemocom.de/2022/02/15/running-ttn-prometheus-exporter-as-systemd-service/","summary":"\u003ch2 id=\"background\"\u003eBackground\u003c/h2\u003e\n\u003cp\u003eIn previous posts we presented a Prometheus exporter to monitor for monitoring TheThingsNetwork gateways. The exporter can directly be executed in a terminal. However, to use it productively it should run in the background as a service. This article demonstrates how this can be achieved using the system and service manager systemd on Linux systems.\u003c/p\u003e\n\u003ch2 id=\"preparation\"\u003ePreparation\u003c/h2\u003e\n\u003cp\u003eThe first step is to prepare the environment where the Prometheus exporter is installed. Throughout this article we will use the directory \u003ccode\u003e/usr/local/bin/prometheus-ttn-exporter\u003c/code\u003e. However, any other directory in the local file system is also possible.\u003c/p\u003e","title":"Running TTN Prometheus Exporter as systemd Service"},{"content":"Background In previous posts we showed how the status of TheThingsNetwork gatways can be monitored. With the switch of the underlying infrastructure to TheThingsStack this becomes even easier, because the API allows direct access to the relevant statistics of the gateways. It is now also possible to authenticate with a (personal) API key, such that the login procedure becomes also easier to handle.\nAPI Key The first step is to create an API key with the appropriate permissions. This can be done in the console of TheThingsNetwork, by clicking on your username in the upper right corner and selecting the option Personal API Keys. You have to create a token with at least the permissions view gateway status and list gateways the user is a collaborator of.\nPrometheus TTN Gateway Exporter The changes of the prometheus exporter are minimal, because the authentication becomes easier with the API key. The main changes are the different API calls compared to the previous version. Besides that the things mentioned in the previous article are still applicable. The code on Github is already updated.\nimport signal import sys import threading import requests from absl import app from absl import flags from absl import logging from cachetools import cached, TTLCache from prometheus_client import start_wsgi_server, Gauge FLAGS = flags.FLAGS flags.DEFINE_string(\u0026#39;listen\u0026#39;, \u0026#39;:9714\u0026#39;, \u0026#39;Address:port to listen on\u0026#39;) flags.DEFINE_string(\u0026#39;key\u0026#39;, None, \u0026#39;API key\u0026#39;) flags.DEFINE_string(\u0026#39;password\u0026#39;, None, \u0026#39;Password to authenticate with\u0026#39;) flags.DEFINE_bool(\u0026#39;verbose\u0026#39;, False, \u0026#39;Enable verbose logging\u0026#39;) exit_app = threading.Event() TOKEN = None EXPIRES = None cache = TTLCache(maxsize=200, ttl=10) @cached(cache) def get_gateway_stats(gateway_id): session = requests.Session() header = {\u0026#39;Authorization\u0026#39;: \u0026#39;Bearer \u0026#39; + FLAGS.key} res = session.get(\u0026#39;https://eu1.cloud.thethings.network/api/v3/gs/gateways/%s/connection/stats\u0026#39; % gateway_id, headers=header) return res.json() @cached(cache) def get_gateway_ids(): session = requests.Session() header = {\u0026#39;Authorization\u0026#39;: \u0026#39;Bearer \u0026#39; + FLAGS.key} res = session.get(\u0026#39;https://eu1.cloud.thethings.network/api/v3/gateways\u0026#39;, headers=header) return [gateway[\u0026#39;ids\u0026#39;][\u0026#39;gateway_id\u0026#39;] for gateway in res.json()[\u0026#39;gateways\u0026#39;]] def collect_metrics(gateway_id, metric) -\u0026gt; int: gateway_stats = get_gateway_stats(gateway_id) if metric in gateway_stats: return int(gateway_stats[metric]) return 0 def prepare_metrics(): logging.debug(\u0026#39;prepare metrics\u0026#39;) for metric in [\u0026#39;uplink_count\u0026#39;, \u0026#39;downlink_count\u0026#39;]: gauge = Gauge(\u0026#39;ttn_gateway_messages_%s\u0026#39; % metric, \u0026#39;Number of %s messages\u0026#39; % metric, labelnames=[\u0026#39;gateway_id\u0026#39;]) for gateway_id in get_gateway_ids(): gauge.labels(gateway_id=gateway_id).set_function(lambda i=gateway_id, m=metric: collect_metrics(i, m)) def quit_app(unused_signo, unused_frame): exit_app.set() def main(unused_argv): if FLAGS.verbose: logging.set_verbosity(logging.DEBUG) if FLAGS.key is None: logging.error(\u0026#39;Provide API key!\u0026#39;) sys.exit(-1) prepare_metrics() address, port = FLAGS.listen.rsplit(\u0026#39;:\u0026#39;, 1) start_wsgi_server(port=int(port), addr=address) logging.info(f\u0026#39;Listening on {FLAGS.listen}\u0026#39;) for sig in (signal.SIGTERM, signal.SIGINT, signal.SIGHUP): signal.signal(sig, quit_app) exit_app.wait() if __name__ == \u0026#39;__main__\u0026#39;: app.run(main) To execute the exporter you need to pass the API key from the previous step by executing python ttn-gateway-exporter.py --key API_KEY.\n","permalink":"https://www.cemocom.de/2022/02/10/the-things-stack-gateway-monitoring/","summary":"\u003ch2 id=\"background\"\u003eBackground\u003c/h2\u003e\n\u003cp\u003eIn previous posts we showed how the status of TheThingsNetwork gatways can be monitored. With the switch of the underlying infrastructure to TheThingsStack this becomes even easier, because the API allows direct access to the relevant statistics of the gateways. It is now also possible to authenticate with a (personal) API key, such that the login procedure becomes also easier to handle.\u003c/p\u003e\n\u003ch2 id=\"api-key\"\u003eAPI Key\u003c/h2\u003e\n\u003cp\u003eThe first step is to create an API key with the appropriate permissions. This can be done in the console of TheThingsNetwork, by clicking on your username in the upper right corner and selecting the option \u003cem\u003ePersonal API Keys\u003c/em\u003e. You have to create a token with at least the permissions \u003cem\u003eview gateway status\u003c/em\u003e and \u003cem\u003elist gateways the user is a collaborator of\u003c/em\u003e.\u003c/p\u003e","title":"The Things Stack Gateway Monitoring"},{"content":"This article deals with a challenge of simulation studies. In particular it deals with traceability. We define what the term traceability means and what is not meant by it. Additionally we illustrate a concept how to achieve traceability with established methods from software engineering.\nWhat is traceability The term traceability describes the fact that all steps necessary to create results with simulation studies are linked with each other. Thereby traceability is the foundation of reproducible simulation results. A basic workflow when producing results out of simulation study consists of the following steps.\nDevelopment of the simulation model Configuring the simulation model Executing the simulation study Collecting the simulation results Post-processing the simulation results, e.g. into plots With traceability it is possible to link all steps. E.g. it is possible to link a plot to the execution environment used to run the study. The execution environment is linked to the configuration of the simulation model and the configuration is finally linked to the source code of the model itself.\nIt is important to mention that traceability does not guarantee that the simulation results are correct. This brings us to the next section, which discusses what traceability is not.\nWhat traceability is not Traceability may not be mixed up with validity or credibility of simulations. While there are methods, partly also known in software engineering, to ensure the correctness of simulations, it is in general much more difficult to guarantee the credibility of simulations.\nThis topic deserves an own article and will be covered in a later post.\nHow to achieve traceability Traceability is already widely adopted in software engineering, even if it is not known under this term. The remainder of this article will discuss these concepts and illustrate how these can be applied to simulation studies.\nVersion control A version control system allows to keep a complete history of changes applied to a set of files. This allows to track all changes as well as to restore older versions. Each version is identified by an unique identifier. While version control systems can manage all kind of files, they work especially well for text based files because there the changes can directly be shown and read by the users of the version control. Therefore, all source code used in simulation studies, e.g. the source code of the model, configuration files, scripts to execute the simulation or collect the results, and also the results themselves, should be manged by version control systems.\nVersioning If the simulation depends on external libraries or tools, the exact version of the tools should be included in the configuration of the study. The configuration itself should be managed by a version control system. Thereby, the different components are linked and traceability is achieved.\nMeta data Finally, meta data allows to embed additional information in other data, e.g. plots of simulation results. A plot should contain the exact version of the simulation environment as meta data. Thereby, it is traceable how this plot has been created and thereby also how the simulation model has been executed and configured and what the exact version of the simulation model was.\n","permalink":"https://www.cemocom.de/2022/01/26/traceability-in-simulation-studies/","summary":"\u003cp\u003eThis article deals with a challenge of simulation studies. In particular it deals with traceability. We define what the term traceability means and what is not meant by it. Additionally we illustrate a concept how to achieve traceability with established methods from software engineering.\u003c/p\u003e\n\u003ch2 id=\"what-is-traceability\"\u003eWhat is traceability\u003c/h2\u003e\n\u003cp\u003eThe term traceability describes the fact that all steps necessary to create results with simulation studies are linked with each other. Thereby traceability is the foundation of reproducible simulation results. A basic workflow when producing results out of simulation study consists of the following steps.\u003c/p\u003e","title":"Traceability in Simulation Studies"},{"content":"Introduction When executing simulations one is often facing the task to running simulation studies with varying parameters. The simulation results are then plotted as a family of curves. Especially in the case of discrete event simulations, the task of running the complete simulation study can be efficiently distributed on multiple compute nodes, as every parameter combination can be treated as an individual simulation. This article describe a scalable yet inexpensive setup to execute such simulation studies.\nAs a disclaimer it shall be mentioned, that scalability of course has limitations and there are good reasons why there are dedicated architectures for high performance computing. Yet for the purpose of discrete event simulations the presented setup is a suitable choice.\nSetup The diagram below depicts the setup, which consists of multiple compute nodes, a central, shared storage system and a node to control the simulation. Even if the diagram shows these roles as individual nodes, a single node can act in multiple roles. E.g. a compute node can act at the same time as storage system or control node. The bottleneck in such a setup is usually the storage system, but alternatives like distributed file systems can improve the performance.\nThe structure of the simulation study, i.e. the different parameters and their values can be directly reflected in the shared file system provided by the central storage system.\nFile System Structure As all nodes share the same file system, the parameters, their values but also the simulation results can be stored in this file system. This allows to manage the simulation study, i.e. adding or removing parameters, with native tools provided by the operating system. But of course the simulation study can also be managed with specialized tools.\nIn the following we will call the file system directory, that holds the simulation study, study root. The study root can one the one hand contain the parameters, values and results, but on the other hand also all scripts or binaries to actually execute the simulation. The listing below shows an example of an empty study root.\n├── MetaData └── Results ├── ParaS__Strategy__ProportionalFair │ ├── ParaF__Load__0.1 │ ├── ParaF__Load__0.5 │ └── ParaF__Load__1.0 └── ParaS__Strategy__RoundRobin ├── ParaF__Load__0.1 ├── ParaF__Load__0.5 └── ParaF__Load__1.0 The directory MetaData contains configuration files, the simulation binaries and parameter file templates. The directory Results holds the structure of the study root, i.e. the parameters and their values. In this case the parameter Strategy of type string with the values ProportionalFair and RoundRobin and the parameter Load of type float with the values 0.1, 0.5 and 1.0 exists. All files created by the simulation binary would be created as leaves of a specific parameter combination.\nThe parameter file template could look as follows.\nNetwork.Load = %%Load%% Scheduler.Strategy = %%Strategy%% Simulation Control The task of the simulation control are twofold. The first task is to manage the study root, i.e. creating it, adding parameters and values. The second task is to actually execute the simulation study. While the first task can also be performed with native programs, the second task requires special tooling.\nTo execute the simulation for a single parameter combination, the simulation control reads the parameter file template located in the directory MetaData, replaces all placeholders with the actual values of the parameters and writes the parameter file in the corresponding leaf in the study root. For example for the parameter combination Strategy = ProportionalFair and Load = 0.1, the simulation control would replace the placeholders %%Strategy%% with ProprtionalFair and %%Load%% with 0.1. The resulting parameter file would be written in the directory ./Results/ParaS__Strategy__ProportionalFair/ParaF__Load__0.1.\nAfter creating the parameter file, the simulation control executes the simulation binary remotely on one of the available compute nodes. Additionally the working directory is set correspondingly and the created parameter file is passed to the simulation binary. For this purpose standard tooling like SSH is used.\nAdditional scheduling rules can be considered by the simulation control, e.g. in order to prioritize some parameter combinations or compute nodes. Also the available capacity of the compute nodes with respect to compute resources or memory can be considered.\nTooling As mention special tooling to manage simulation studies exists. An example of such a tool is IKR SimTree which is developed by the Institute of Communication Networks and Computer Engineering of the University of Stuttgart. However, IKR SimTree is not actively maintained and has some special dependencies to the infrastructure it is executed on.\nThis is why we will publish a complete rewrite name SimTreeNG in the near future. Also, we will discuss in future articles the details of the setup we briefly introduces in this article.\n","permalink":"https://www.cemocom.de/2021/06/21/scalable-setup-for-simulation-studies/","summary":"\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cp\u003eWhen executing simulations one is often facing the task to running simulation studies with varying parameters. The simulation results are then plotted as a family of curves. Especially in the case of discrete event simulations, the task of running the complete simulation study can be efficiently distributed on multiple compute nodes, as every parameter combination can be treated as an individual simulation. This article describe a scalable yet inexpensive setup to execute such simulation studies.\u003c/p\u003e","title":"Scalable Setup for Simulation Studies"},{"content":"In a previous article we showed how an own TTN LoRaWAN gateway can be built using a Raspberry Pi. This article shows how a LoRaWAN device can be built. There are multiple options, however we use an Adafruit Feather.\nThere are multiple tutorials available. For example Adafruit provides a detailed guide.\nAdafruit Feather The Adafruit Feathers are a family of micro-controllers. All share the same layout such that extensions in the form of so called Wings can be used. Some Feathers already contain sensors or communication modules. For example the Adafruit Feather M0 is also available with a LoRaWAN communication module.\nAll Feathers can be programmed using the Arduino IDE such that it is very easy to get started. Consequently the Adafruit Feathers are a good solution for many IoT solutions.\nThe Feather M0 is almost ready to use. The only necessary steps are to add a jumper wire and to solder an antenna to it. For the 868 MHz frequency range a simple wire with a length of 8,2 cm is sufficient as antenna. For first tests the Feather M0 can be connected via its USB port for power supply.\nCreate a TTN Application The next step is to create a new TTN application. This can be done by logging in to https://console.thethingsnetwork.org. After logging in select applications and create a new application. A dialog opens where the details of the new application can be entered.\nAfter creating the application devices can be added to the application a new dialog is shown that lists all details about the application.\nThis dialog also shows all devices connected to the application. As we just created the application there are no devices available yet. But we can register a new device. For the registration we have to provide application wide unique device identifier and the network wide unique Device EUI. The Device EUI is a eight byte sequence. Use the identifier that was included with your Adafruit Feather. Pad with zero bytes if necessary. If the Device EUI is not know there is also the possibility to generate a random one.\nIn the next dialog the relevant information to finally activate the device is shown. The Device EUI, Application EUI and App Key can be directly displayed in the correct format. Important for the next steps is that D evice EUI and Application EUI are provided in LSB order.\nProgram the Adafruit Feather The complete set-up of the Arduino IDE is skipped in this article. The most important steps are shown in the Adafruit tutorial. We use the MCCI\u0026rsquo;s arduino-lmic library to communicate with the TTN network, which can be installed using the library manager of the Arduino IDE. In the example below we do not transmit useful data, but only randomly generated data. In real implementations the function void readValues(unsigned char *vals) (line 182) could be used to write meaningful data into the variable vals.\nThe Device EUI, Application EUI and App Key from the previous steps have to be copied into the variables PROGMEM DEVEUI, PROGMEM APPEUI and PROGMEM APPKEY, respectively. These variables are located in the beginning of the code. Finally the transmit interval in seconds can be configured via the variable TX_INTERVAL in line 60.\nBefore flashing the program on the Feather M0, it is necessary to configure the region, i.e. the frequency, that shall be used. This is done in the file lmic_project_config.h located in the LMIC library folder of your Arduino IDE. Simply uncomment the region in which the device shall be used. Make sure that only one region is uncommented.\n/******************************************************************************* Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman Adapted for Adafruit feather m0 LoRa by Stefan Huber Permission is hereby granted, free of charge, to anyone obtaining a copy of this document and accompanying files, to do whatever they want with them without any restriction, including, but not limited to, copying, modification and redistribution. NO WARRANTY OF ANY KIND IS PROVIDED. This example sends the actual battery voltage, using frequency and encryption settings matching those of the The Things Network. This uses OTAA (Over-the-air activation), where where a DevEUI and application key is configured, which are used in an over-the-air activation procedure where a DevAddr and session keys are assigned/generated for use with all further communication. Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in g1, 0.1% in g2), but not the TTN fair usage policy (which is probably violated by this sketch when left running for longer)! To use this sketch, first register your application and device with the things network, to set or generate an AppEUI, DevEUI and AppKey. Multiple devices can use the same AppEUI, but each device has its own DevEUI and AppKey. Do not forget to define the radio type correctly in config.h. *******************************************************************************/ #include \u0026lt;lmic.h\u0026gt; #include \u0026lt;hal/hal.h\u0026gt; #include \u0026lt;SPI.h\u0026gt; #include \u0026lt;avr/dtostrf.h\u0026gt; // This EUI must be in little-endian format, so least-significant-byte first. static const u1_t PROGMEM APPEUI[8] = {}; void os_getArtEui(u1_t *buf) { memcpy_P(buf, APPEUI, 8); } // This should also be in little endian format, see above. static const u1_t PROGMEM DEVEUI[8] = {}; void os_getDevEui(u1_t *buf) { memcpy_P(buf, DEVEUI, 8); } // This key should be in big endian format. static const u1_t PROGMEM APPKEY[16] = {}; void os_getDevKey(u1_t *buf) { memcpy_P(buf, APPKEY, 16); } char mydata[16]; static osjob_t sendjob; const unsigned TX_INTERVAL = 600; const lmic_pinmap lmic_pins = { .nss = 8, .rxtx = LMIC_UNUSED_PIN, .rst = LMIC_UNUSED_PIN, .dio = {3, 6, LMIC_UNUSED_PIN}, }; void printHex2(unsigned v) { v \u0026amp;= 0xff; if (v \u0026lt; 16) { Serial.print(\u0026#39;0\u0026#39;); } Serial.print(v, HEX); } void onEvent(ev_t ev) { Serial.print(os_getTime()); Serial.print(\u0026#34;: \u0026#34;); switch (ev) { case EV_SCAN_TIMEOUT: Serial.println(F(\u0026#34;EV_SCAN_TIMEOUT\u0026#34;)); break; case EV_BEACON_FOUND: Serial.println(F(\u0026#34;EV_BEACON_FOUND\u0026#34;)); break; case EV_BEACON_MISSED: Serial.println(F(\u0026#34;EV_BEACON_MISSED\u0026#34;)); break; case EV_BEACON_TRACKED: Serial.println(F(\u0026#34;EV_BEACON_TRACKED\u0026#34;)); break; case EV_JOINING: Serial.println(F(\u0026#34;EV_JOINING\u0026#34;)); break; case EV_JOINED: Serial.println(F(\u0026#34;EV_JOINED\u0026#34;)); { u4_t netid = 0; devaddr_t devaddr = 0; u1_t nwkKey[16]; u1_t artKey[16]; LMIC_getSessionKeys(\u0026amp;netid, \u0026amp;devaddr, nwkKey, artKey); Serial.print(\u0026#34;netid: \u0026#34;); Serial.println(netid, DEC); Serial.print(\u0026#34;devaddr: \u0026#34;); Serial.println(devaddr, HEX); Serial.print(\u0026#34;AppSKey: \u0026#34;); for (size_t i = 0; i \u0026lt; sizeof(artKey); ++i) { if (i != 0) Serial.print(\u0026#34;-\u0026#34;); printHex2(artKey[i]); } Serial.println(\u0026#34;\u0026#34;); Serial.print(\u0026#34;NwkSKey: \u0026#34;); for (size_t i = 0; i \u0026lt; sizeof(nwkKey); ++i) { if (i != 0) Serial.print(\u0026#34;-\u0026#34;); printHex2(nwkKey[i]); } Serial.println(); } LMIC_setLinkCheckMode(0); break; case EV_JOIN_FAILED: Serial.println(F(\u0026#34;EV_JOIN_FAILED\u0026#34;)); break; case EV_REJOIN_FAILED: Serial.println(F(\u0026#34;EV_REJOIN_FAILED\u0026#34;)); break; case EV_TXCOMPLETE: Serial.println(F(\u0026#34;EV_TXCOMPLETE (includes waiting for RX windows)\u0026#34;)); if (LMIC.txrxFlags \u0026amp; TXRX_ACK) Serial.println(F(\u0026#34;Received ack\u0026#34;)); if (LMIC.dataLen) { Serial.println(F(\u0026#34;Received \u0026#34;)); Serial.println(LMIC.dataLen); Serial.println(F(\u0026#34; bytes of payload\u0026#34;)); } os_setTimedCallback(\u0026amp;sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send); break; case EV_LOST_TSYNC: Serial.println(F(\u0026#34;EV_LOST_TSYNC\u0026#34;)); break; case EV_RESET: Serial.println(F(\u0026#34;EV_RESET\u0026#34;)); break; case EV_RXCOMPLETE: Serial.println(F(\u0026#34;EV_RXCOMPLETE\u0026#34;)); break; case EV_LINK_DEAD: Serial.println(F(\u0026#34;EV_LINK_DEAD\u0026#34;)); break; case EV_LINK_ALIVE: Serial.println(F(\u0026#34;EV_LINK_ALIVE\u0026#34;)); break; case EV_TXSTART: Serial.println(F(\u0026#34;EV_TXSTART\u0026#34;)); break; case EV_TXCANCELED: Serial.println(F(\u0026#34;EV_TXCANCELED\u0026#34;)); break; case EV_RXSTART: break; case EV_JOIN_TXCOMPLETE: Serial.println(F(\u0026#34;EV_JOIN_TXCOMPLETE: no JoinAccept\u0026#34;)); break; default: Serial.print(F(\u0026#34;Unknown event: \u0026#34;)); Serial.println((unsigned)ev); break; } } void readValues(unsigned char *vals) { vals[0] = (unsigned char)rand(); } void do_send(osjob_t *j) { // Check if there is not a current TX/RX job running if (LMIC.opmode \u0026amp; OP_TXRXPEND) { Serial.println(F(\u0026#34;OP_TXRXPEND, not sending\u0026#34;)); } else { // Prepare upstream data transmission at the next possible time. unsigned char payload; readValues(\u0026amp;payload); Serial.print(\u0026#34;Payload: \u0026#34;); Serial.println(payload); LMIC_setTxData2(1, \u0026amp;payload, 1, 0); Serial.println(F(\u0026#34;Packet queued\u0026#34;)); } // Next TX is scheduled after TX_COMPLETE event. } void setup() { Serial.begin(9600); delay(10000); Serial.println(F(\u0026#34;Starting\u0026#34;)); // LMIC init os_init(); // Reset the MAC state. Session and pending data transfers will be discarded. LMIC_reset(); LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); // Start job (sending automatically starts OTAA too) do_send(\u0026amp;sendjob); } void loop() { os_runloop_once(); } Conclusion This article demonstrated the necessary steps to create a new TTN application and connect an Adafruit Feather M0 to it.\nThe next step would be to consume the transmitted data of the devices. The TTN console provides the possibility for data conversion using small JavaScript scripts. The received data can also be exported to own services, e.g. via MQTT or HTTP. This will be covered in a follow-up article.\n","permalink":"https://www.cemocom.de/2020/12/30/adafruit-feather-m0-as-lorawan-device/","summary":"\u003cp\u003eIn a \u003ca href=\"/2020/12/12/building-a-lorawan-gateway/\"\u003eprevious article\u003c/a\u003e we showed how an own TTN LoRaWAN gateway can be built using a Raspberry Pi. This article shows how a LoRaWAN device can be built. There are multiple options, however we use an Adafruit Feather.\u003c/p\u003e\n\u003cp\u003eThere are multiple tutorials available. For example Adafruit provides a \u003ca href=\"https://learn.adafruit.com/the-things-network-for-feather\"\u003edetailed guide\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"adafruit-feather\"\u003eAdafruit Feather\u003c/h2\u003e\n\u003cp\u003eThe \u003ca href=\"https://www.adafruit.com/feather\"\u003eAdafruit Feathers\u003c/a\u003e are a family of micro-controllers. All share the same layout such that extensions in the form of so called \u003ca href=\"https://www.adafruit.com/category/814\"\u003eWings\u003c/a\u003e can be used. Some Feathers already contain sensors or communication modules. For example the \u003ca href=\"https://learn.adafruit.com/adafruit-feather-m0-radio-with-lora-radio-module\"\u003eAdafruit Feather M0\u003c/a\u003e is also available with a LoRaWAN communication module.\u003c/p\u003e","title":"Adafruit Feather M0 as LoRaWAN Device"},{"content":"In a previous post we showed how TTN gateways can be monitored using Prometheus. However, the presented solution had some limitations. For example it was only possible to monitor a single gateway. Also the code is now available on GitHub.\nTo support multiple gateways the output format has slightly be changed. The metrics for the different gateways can now be filtered by the label gateway_id.\n# HELP python_gc_objects_collected_total Objects collected during gc # TYPE python_gc_objects_collected_total counter python_gc_objects_collected_total{generation=\u0026#34;0\u0026#34;} 48.0 python_gc_objects_collected_total{generation=\u0026#34;1\u0026#34;} 344.0 python_gc_objects_collected_total{generation=\u0026#34;2\u0026#34;} 0.0 # HELP python_gc_objects_uncollectable_total Uncollectable object found during GC # TYPE python_gc_objects_uncollectable_total counter python_gc_objects_uncollectable_total{generation=\u0026#34;0\u0026#34;} 0.0 python_gc_objects_uncollectable_total{generation=\u0026#34;1\u0026#34;} 0.0 python_gc_objects_uncollectable_total{generation=\u0026#34;2\u0026#34;} 0.0 # HELP python_gc_collections_total Number of times this generation was collected # TYPE python_gc_collections_total counter python_gc_collections_total{generation=\u0026#34;0\u0026#34;} 59.0 python_gc_collections_total{generation=\u0026#34;1\u0026#34;} 5.0 python_gc_collections_total{generation=\u0026#34;2\u0026#34;} 0.0 # HELP python_info Python platform information # TYPE python_info gauge python_info{implementation=\u0026#34;CPython\u0026#34;,major=\u0026#34;3\u0026#34;,minor=\u0026#34;9\u0026#34;,patchlevel=\u0026#34;1\u0026#34;,version=\u0026#34;3.9.1\u0026#34;} 1.0 # HELP process_virtual_memory_bytes Virtual memory size in bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 1.87236352e+08 # HELP process_resident_memory_bytes Resident memory size in bytes. # TYPE process_resident_memory_bytes gauge process_resident_memory_bytes 3.1379456e+07 # HELP process_start_time_seconds Start time of the process since unix epoch in seconds. # TYPE process_start_time_seconds gauge process_start_time_seconds 1.60917394427e+09 # HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. # TYPE process_cpu_seconds_total counter process_cpu_seconds_total 0.13999999999999999 # HELP process_open_fds Number of open file descriptors. # TYPE process_open_fds gauge process_open_fds 8.0 # HELP process_max_fds Maximum number of open file descriptors. # TYPE process_max_fds gauge process_max_fds 1024.0 # HELP ttn_gateway_messages_uplink Number of uplink messages # TYPE ttn_gateway_messages_uplink gauge ttn_gateway_messages_uplink{gateway_id=\u0026#34;eui-1\u0026#34;} 10.0 ttn_gateway_messages_uplink{gateway_id=\u0026#34;eui-2\u0026#34;} 20.0 # HELP ttn_gateway_messages_downlink Number of downlink messages # TYPE ttn_gateway_messages_downlink gauge ttn_gateway_messages_downlink{gateway_id=\u0026#34;eui-1\u0026#34;} 1.0 ttn_gateway_messages_downlink{gateway_id=\u0026#34;eui-2\u0026#34;} 2.0 # HELP ttn_gateway_messages_rx_ok Number of rx_ok messages # TYPE ttn_gateway_messages_rx_ok gauge ttn_gateway_messages_rx_ok{gateway_id=\u0026#34;eui-1\u0026#34;} 10.0 ttn_gateway_messages_rx_ok{gateway_id=\u0026#34;eui-2\u0026#34;} 20.0 # HELP ttn_gateway_messages_tx_in Number of tx_in messages # TYPE ttn_gateway_messages_tx_in gauge ttn_gateway_messages_tx_in{gateway_id=\u0026#34;eui-1\u0026#34;} 1.0 ttn_gateway_messages_tx_in{gateway_id=\u0026#34;eui-02c10afffe41d2a3\u0026#34;} 2.0 ","permalink":"https://www.cemocom.de/2020/12/28/improved-thethingsnetwork-monitoring/","summary":"\u003cp\u003eIn a \u003ca href=\"/2020/12/16/thethingsnetwork-gateway-monitoring/\"\u003eprevious post\u003c/a\u003e we showed how TTN gateways can be monitored using Prometheus. However, the presented solution had some limitations. For example it was only possible to monitor a single gateway. Also the code is now available on \u003ca href=\"https://github.com/sebassz/prometheus-ttn-gateway-exporter\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eTo support multiple gateways the output format has slightly be changed. The metrics for the different gateways can now be filtered by the label \u003cem\u003egateway_id\u003c/em\u003e.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP python_gc_objects_collected_total Objects collected during gc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE python_gc_objects_collected_total counter\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_objects_collected_total{generation=\u0026#34;0\u0026#34;} 48.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_objects_collected_total{generation=\u0026#34;1\u0026#34;} 344.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_objects_collected_total{generation=\u0026#34;2\u0026#34;} 0.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP python_gc_objects_uncollectable_total Uncollectable object found during GC\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE python_gc_objects_uncollectable_total counter\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_objects_uncollectable_total{generation=\u0026#34;0\u0026#34;} 0.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_objects_uncollectable_total{generation=\u0026#34;1\u0026#34;} 0.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_objects_uncollectable_total{generation=\u0026#34;2\u0026#34;} 0.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP python_gc_collections_total Number of times this generation was collected\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE python_gc_collections_total counter\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_collections_total{generation=\u0026#34;0\u0026#34;} 59.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_collections_total{generation=\u0026#34;1\u0026#34;} 5.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_gc_collections_total{generation=\u0026#34;2\u0026#34;} 0.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP python_info Python platform information\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE python_info gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython_info{implementation=\u0026#34;CPython\u0026#34;,major=\u0026#34;3\u0026#34;,minor=\u0026#34;9\u0026#34;,patchlevel=\u0026#34;1\u0026#34;,version=\u0026#34;3.9.1\u0026#34;} 1.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP process_virtual_memory_bytes Virtual memory size in bytes.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE process_virtual_memory_bytes gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprocess_virtual_memory_bytes 1.87236352e+08\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP process_resident_memory_bytes Resident memory size in bytes.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE process_resident_memory_bytes gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprocess_resident_memory_bytes 3.1379456e+07\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE process_start_time_seconds gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprocess_start_time_seconds 1.60917394427e+09\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE process_cpu_seconds_total counter\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprocess_cpu_seconds_total 0.13999999999999999\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP process_open_fds Number of open file descriptors.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE process_open_fds gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprocess_open_fds 8.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP process_max_fds Maximum number of open file descriptors.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE process_max_fds gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprocess_max_fds 1024.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP ttn_gateway_messages_uplink Number of uplink messages\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE ttn_gateway_messages_uplink gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_uplink{gateway_id=\u0026#34;eui-1\u0026#34;} 10.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_uplink{gateway_id=\u0026#34;eui-2\u0026#34;} 20.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP ttn_gateway_messages_downlink Number of downlink messages\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE ttn_gateway_messages_downlink gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_downlink{gateway_id=\u0026#34;eui-1\u0026#34;} 1.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_downlink{gateway_id=\u0026#34;eui-2\u0026#34;} 2.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP ttn_gateway_messages_rx_ok Number of rx_ok messages\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE ttn_gateway_messages_rx_ok gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_rx_ok{gateway_id=\u0026#34;eui-1\u0026#34;} 10.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_rx_ok{gateway_id=\u0026#34;eui-2\u0026#34;} 20.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# HELP ttn_gateway_messages_tx_in Number of tx_in messages\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# TYPE ttn_gateway_messages_tx_in gauge\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_tx_in{gateway_id=\u0026#34;eui-1\u0026#34;} 1.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ettn_gateway_messages_tx_in{gateway_id=\u0026#34;eui-02c10afffe41d2a3\u0026#34;} 2.0\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Improved TheThingsNetwork Gateway Monitoring"},{"content":"This article demonstrates how the POCSAG pager network can be monitored and the transmitted messages can be read.\nBackground The POCSAG protocol used to operate pager networks is already several decades old but still in use. There are multiple networks available world wide operated by commercial network operators. The communication is by default unencrypted so it can be received and understood by anyone.\nThis article shows how a SDR and open source software can be used to receive and display POCSAG messages.\nNeeded Hardware and Software The needed hardware is quite inexpensive and the software is available as open source, such that the entry barrier to start own experiments is quite low.\nHardware In principle any software defined radio (SDR) covering a frequency range up to 800 MHz should be suitable to monitor POCSAG communication. This includes also RTL-SDR USB sticks which allow an inexpensive start into the SDR world. The RTL-SDR was initially produced as DVB-T tuner and is available for around 25€. However, we use a LimeSDR receiver in this article.\nSoftware The following software is necessary. In a Linux system it can usually directly be installed using the distribution\u0026rsquo;s package management system. Additionally appropriate drivers for the used SDR are required.\nGQRX SoX multimon-ng GQRX is graphical frontend for the SDR. It is used to configure the SDR, e.g. the correct frequency or modulation scheme. It also offers the possibility to to forward the received signal stream via UDP to other applications.\nSoX is the self-claimed Swiss army knife of sound processing programs. It is used to down-sample the received signal stream from GQRX such that it can be processed by the final program - multimon-ng.\nMultimon-ng is able to decode multiple digital communication protocols. The list of supported protocols includes also POCSAG.\nConfiguration The first step is to figure out which POCSAG networks are available in your region and on which frequency they are operating. As a starting point have a look in this Wikipedia article.\nDepending on the used SDR device, the configuration of GQRX is different. For a LimeSDR the following configuration works.\nThe receiver options can be configures as shown in the next picture. The AGC as well as the squelch options can still be improved depending on the used hardware.\nThe input controls as shown as in the next image can act as a starting point. Fine tuning of the gain controls is recommended as these depend on the used hardware equipment.\nThe final configuration step in GQRX is to enable UDP output such that the received and demodulated audio signal can be used by other programs. This can be done by selecting the UDP button on the lower right window. By default GQRX opens a UDP socket on port 7355.\nThe decoding of the received signal is done with multimon-ng. It can be started in a console with the following command.\nnc -l -u localhost 7355 | sox -t raw -esigned-integer -b16 -r 48000 - -t raw -esigned-integer -b16 -r 22050 - | multimon-ng -t raw -a POCSAG512 -a POCSAG1200 -a POCSAG2400 -f alpha -e --timestamp - After a while you should be able to see decoded messages in the terminal window.\n","permalink":"https://www.cemocom.de/2020/12/22/monitoring-pocsag-networks-using-a-sdr/","summary":"\u003cp\u003eThis article demonstrates how the POCSAG pager network can be monitored and the transmitted messages can be read.\u003c/p\u003e\n\u003ch2 id=\"background\"\u003eBackground\u003c/h2\u003e\n\u003cp\u003eThe POCSAG protocol used to operate pager networks is already several decades old but still in use. There are multiple networks available world wide operated by commercial network operators. The communication is by default unencrypted so it can be received and understood by anyone.\u003c/p\u003e\n\u003cp\u003eThis article shows how a SDR and open source software can be used to receive and display POCSAG messages.\u003c/p\u003e","title":"Monitoring POCSAG Networks using a SDR"},{"content":"Background In a previous post we showed how to setup a new TheThingsNetwork gateway. After successfully building a gateway and connecting it to TTN, probably one of the most interesting information for gateway operators is how frequently the gateway is used. This information is available on the TheThingsNetwork Console, but of course we want to access this data via API so that we can use it in multiple ways. One option would be to create a Grafana dashboard and display the transmitted and received messages. TTN provides a public API, but there the interesting information is not included.\nReverse Engineering the TTN API If we have a closer look on the requests the TTN console performs to display the number of transmitted messages, we can identify the following requests.\nPOST https://account.thethingsnetwork.org/api/v2/users/login In this request we have to provide our credentials as body as {\u0026quot;username\u0026quot;: \u0026quot;user\u0026quot;, \u0026quot;password\u0026quot;: \u0026quot;pass\u0026quot;}. After a successful response we also receive one session cookie for thethingsnetwork.org and two cookies for account.thethingsnetwork.org. With these cookies we can perform the second request.\nGET https://console.thethingsnetwork.org With this request we obtain three cookies for console.thethingsnetwork.org and we can directly perform the next request.\nGET https://console.thethingsnetwork.org/refresh This requests provides us the required JWT access token and its expiration data in its response. Using the token we obtain the gateway information in our last request.\nGET https://console.thethingsnetwork.org/api/gateways We have to use the access token from the previous request as bearer token and obtain the following JSON object.\n[ { \u0026#34;id\u0026#34;: \u0026#34;eui-123\u0026#34;, \u0026#34;activated\u0026#34;: false, \u0026#34;frequency_plan\u0026#34;: \u0026#34;EU_863_870\u0026#34;, \u0026#34;frequency_plan_url\u0026#34;: \u0026#34;https://account.thethingsnetwork.org/api/v2/frequency-plans/EU_863_870\u0026#34;, \u0026#34;auto_update\u0026#34;: false, \u0026#34;location_public\u0026#34;: true, \u0026#34;status_public\u0026#34;: true, \u0026#34;owner_public\u0026#34;: false, \u0026#34;antenna_location\u0026#34;: { \u0026#34;longitude\u0026#34;: 9.0, \u0026#34;latitude\u0026#34;: 48.0, \u0026#34;altitude\u0026#34;: 0 }, \u0026#34;collaborators\u0026#34;: [ { \u0026#34;username\u0026#34;: \u0026#34;username\u0026#34;, \u0026#34;rights\u0026#34;: [ \u0026#34;gateway:settings\u0026#34;, \u0026#34;gateway:collaborators\u0026#34;, \u0026#34;gateway:status\u0026#34;, \u0026#34;gateway:delete\u0026#34;, \u0026#34;gateway:location\u0026#34;, \u0026#34;gateway:owner\u0026#34;, \u0026#34;gateway:messages\u0026#34; ] } ], \u0026#34;key\u0026#34;: \u0026#34;ttn-account-key\u0026#34;, \u0026#34;attributes\u0026#34;: { \u0026#34;brand\u0026#34;: \u0026#34;Multi-channel Raspberry Pi gateway\u0026#34;, \u0026#34;model\u0026#34;: \u0026#34;Raspberry Pi with IMST iC880A\u0026#34;, \u0026#34;placement\u0026#34;: \u0026#34;indoor\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;TTN Gateway\u0026#34; }, \u0026#34;router\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;ttn-router-eu\u0026#34;, \u0026#34;address\u0026#34;: \u0026#34;eu.thethings.network:1901\u0026#34;, \u0026#34;mqtt_address\u0026#34;: \u0026#34;mqtts://bridge.eu.thethings.network:8882\u0026#34; }, \u0026#34;fallback_routers\u0026#34;: [ { \u0026#34;id\u0026#34;: \u0026#34;ttn-router-asia-se\u0026#34;, \u0026#34;address\u0026#34;: \u0026#34;asia-se.thethings.network:1901\u0026#34;, \u0026#34;mqtt_address\u0026#34;: \u0026#34;mqtts://bridge.asia-se.thethings.network\u0026#34; }, { \u0026#34;id\u0026#34;: \u0026#34;ttn-router-us-west\u0026#34;, \u0026#34;address\u0026#34;: \u0026#34;us-west.thethings.network:1901\u0026#34;, \u0026#34;mqtt_address\u0026#34;: \u0026#34;mqtts://bridge.us-west.thethings.network\u0026#34; }, { \u0026#34;id\u0026#34;: \u0026#34;ttn-router-brazil\u0026#34;, \u0026#34;address\u0026#34;: \u0026#34;brazil.thethings.network:1901\u0026#34;, \u0026#34;mqtt_address\u0026#34;: \u0026#34;mqtts://bridge.brazil.thethings.network\u0026#34; } ], \u0026#34;beta_updates\u0026#34;: false, \u0026#34;owner\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;username\u0026#34;: \u0026#34;\u0026#34; }, \u0026#34;rights\u0026#34;: null, \u0026#34;status\u0026#34;: { \u0026#34;timestamp\u0026#34;: \u0026#34;2020-12-14T20:05:14.926987683Z\u0026#34;, \u0026#34;uplink\u0026#34;: 30, \u0026#34;downlink\u0026#34;: 8, \u0026#34;location\u0026#34;: {}, \u0026#34;gps\u0026#34;: {}, \u0026#34;time\u0026#34;: 1607976314926987683, \u0026#34;rx_ok\u0026#34;: 30, \u0026#34;tx_in\u0026#34;: 8 } } ] The interesting information is the status section at the bottom of the JSON response, which shows the total number of transmitted uplink and downlink messages.\nPrometheus TTN Gateway Exporter Using the information we have gathered so far, we can build a simple Prometheus exporter written in Python. The exporter performs the requests shown in the previous section and exposes the the number of uplink and downlink messages. For this a Web server provided by the prometheus_client library is used. This library also allows us the expose the TTN gateway statistics in a format that can directly be scraped by Prometheus. The source is shown in the following. Please note that the implementation has several limitations. E.g. only one gateway is supported at the moment.\nimport datetime import random import signal import threading import requests from absl import app from absl import flags from absl import logging from cachetools import cached, TTLCache from prometheus_client import start_wsgi_server, Gauge FLAGS = flags.FLAGS flags.DEFINE_string(\u0026#39;listen\u0026#39;, \u0026#39;:9714\u0026#39;, \u0026#39;Address:port to listen on\u0026#39;) flags.DEFINE_string(\u0026#39;username\u0026#39;, None, \u0026#39;Username to authenticate with\u0026#39;) flags.DEFINE_string(\u0026#39;password\u0026#39;, None, \u0026#39;Password to authenticate with\u0026#39;) flags.DEFINE_bool(\u0026#39;verbose\u0026#39;, False, \u0026#39;Enable verbose logging\u0026#39;) exit_app = threading.Event() TOKEN = None EXPIRES = None def get_token(session): global TOKEN global EXPIRES logging.debug(\u0026#39;get_token\u0026#39;) now = datetime.datetime.now() if TOKEN and EXPIRES and EXPIRES \u0026gt; now: logging.debug(\u0026#39;reuse existing token\u0026#39;) return TOKEN else: logging.debug(\u0026#39;get new token\u0026#39;) login = {\u0026#39;username\u0026#39;: FLAGS.username, \u0026#39;password\u0026#39;: FLAGS.password} res = session.post(\u0026#39;https://account.thethingsnetwork.org/api/v2/users/login\u0026#39;, data=login) res = session.get(\u0026#39;https://console.thethingsnetwork.org\u0026#39;) res = session.get(\u0026#39;https://console.thethingsnetwork.org/refresh\u0026#39;) json = res.json() TOKEN = json[\u0026#39;access_token\u0026#39;] EXPIRES = datetime.datetime.fromtimestamp(json[\u0026#39;expires\u0026#39;] / 1000) return TOKEN cache = TTLCache(maxsize=200, ttl=10) def hashkey(*args, **kwargs): return args[0] @cached(cache, key=hashkey) def collect_metrics(metric): logging.debug(\u0026#39;collect_metrics %s\u0026#39; % metric) session = requests.Session() local_token = get_token(session) header = {\u0026#39;Authorization\u0026#39;: \u0026#39;Bearer \u0026#39; + local_token} res = session.get(\u0026#39;https://console.thethingsnetwork.org/api/gateways\u0026#39;, headers=header) gateways = res.json() gateway = gateways[0] if metric == \u0026#39;uplink\u0026#39;: return gateway[\u0026#39;status\u0026#39;][\u0026#39;uplink\u0026#39;] elif metric == \u0026#39;downlink\u0026#39;: return gateway[\u0026#39;status\u0026#39;][\u0026#39;downlink\u0026#39;] return random.random() def prepare_metrics(): logging.debug(\u0026#39;prepare metrics\u0026#39;) for metric in [\u0026#39;uplink\u0026#39;, \u0026#39;downlink\u0026#39;]: g = Gauge(\u0026#39;ttn_gateway_%s\u0026#39; % metric, \u0026#39;Number of %s messages processed by the gateway\u0026#39; % metric) g.set_function(lambda m=metric: collect_metrics(m)) def quit_app(unused_signo, unused_frame): exit_app.set() def main(unused_argv): if FLAGS.verbose: logging.set_verbosity(logging.DEBUG) if FLAGS.username is None or FLAGS.password is None: logging.error(\u0026#39;Provide username and password!\u0026#39;) exit(-1) logging.info(FLAGS.password) prepare_metrics() address, port = FLAGS.listen.rsplit(\u0026#39;:\u0026#39;, 1) start_wsgi_server(port=int(port), addr=address) logging.info(f\u0026#39;Listening on {FLAGS.listen}\u0026#39;) for sig in (signal.SIGTERM, signal.SIGINT, signal.SIGHUP): signal.signal(sig, quit_app) exit_app.wait() if __name__ == \u0026#39;__main__\u0026#39;: app.run(main) To execute the Python script a few requirements have to be met. These are:\nabsl-py requests prometheus_client cachetools After installing the requirements, the script can be executed with python ttn-gateway-exporter.py --username user --password pass. By default it listens on port 9714 on all network interfaces of the local machine. You are now able to access the metrics on http://localhost:9714. Besides the TTN statistics, named ttn_gateway_uplink and ttn_gateway_downlink also the Prometheus Python library returns also information about the process itself. An example output is shown below.\n# HELP python_gc_objects_collected_total Objects collected during gc # TYPE python_gc_objects_collected_total counter python_gc_objects_collected_total{generation=\u0026#34;0\u0026#34;} 7468.0 python_gc_objects_collected_total{generation=\u0026#34;1\u0026#34;} 3830.0 python_gc_objects_collected_total{generation=\u0026#34;2\u0026#34;} 0.0 # HELP python_gc_objects_uncollectable_total Uncollectable object found during GC # TYPE python_gc_objects_uncollectable_total counter python_gc_objects_uncollectable_total{generation=\u0026#34;0\u0026#34;} 0.0 python_gc_objects_uncollectable_total{generation=\u0026#34;1\u0026#34;} 0.0 python_gc_objects_uncollectable_total{generation=\u0026#34;2\u0026#34;} 0.0 # HELP python_gc_collections_total Number of times this generation was collected # TYPE python_gc_collections_total counter python_gc_collections_total{generation=\u0026#34;0\u0026#34;} 83.0 python_gc_collections_total{generation=\u0026#34;1\u0026#34;} 7.0 python_gc_collections_total{generation=\u0026#34;2\u0026#34;} 0.0 # HELP python_info Python platform information # TYPE python_info gauge python_info{implementation=\u0026#34;CPython\u0026#34;,major=\u0026#34;3\u0026#34;,minor=\u0026#34;7\u0026#34;,patchlevel=\u0026#34;3\u0026#34;,version=\u0026#34;3.7.3\u0026#34;} 1.0 # HELP process_virtual_memory_bytes Virtual memory size in bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 8.8424448e+07 # HELP process_resident_memory_bytes Resident memory size in bytes. # TYPE process_resident_memory_bytes gauge process_resident_memory_bytes 3.2833536e+07 # HELP process_start_time_seconds Start time of the process since unix epoch in seconds. # TYPE process_start_time_seconds gauge process_start_time_seconds 1.60797857466e+09 # HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. # TYPE process_cpu_seconds_total counter process_cpu_seconds_total 3364.25 # HELP process_open_fds Number of open file descriptors. # TYPE process_open_fds gauge process_open_fds 24.0 # HELP process_max_fds Maximum number of open file descriptors. # TYPE process_max_fds gauge process_max_fds 1024.0 # HELP ttn_gateway_uplink Number of uplink messages processed by the gateway # TYPE ttn_gateway_uplink gauge ttn_gateway_uplink 33.0 # HELP ttn_gateway_downlink Number of downlink messages processed by the gateway # TYPE ttn_gateway_downlink gauge ttn_gateway_downlink 9.0 Outlook In the future an improved version of the Prometheus exporter might be provided. For now just use the shared code snippets and adapt them to your needs.\n","permalink":"https://www.cemocom.de/2020/12/16/thethingsnetwork-gateway-monitoring/","summary":"\u003ch2 id=\"background\"\u003eBackground\u003c/h2\u003e\n\u003cp\u003eIn a \u003ca href=\"/2020/12/12/building-a-lorawan-gateway/\"\u003eprevious post\u003c/a\u003e we showed how to setup a new TheThingsNetwork gateway. After successfully building a gateway and connecting it to TTN, probably one of the most interesting information for gateway operators is how frequently the gateway is used. This information is available on the \u003ca href=\"https://console.thethingsnetwork.org/gateways/\"\u003eTheThingsNetwork Console\u003c/a\u003e, but of course we want to access this data via API so that we can use it in multiple ways. One option would be to create a Grafana dashboard and display the transmitted and received messages. TTN provides a \u003ca href=\"https://www.thethingsnetwork.org/docs/network/account/api.html\"\u003epublic API\u003c/a\u003e, but there the interesting information is not included.\u003c/p\u003e","title":"TheThingsNetwork Gateway Monitoring"},{"content":"Background Long Range Wide Area Network (LoRaWAN) is a proprietary wireless communication protocol. While the achievable data rates are by design comparatively low, it offers long communication ranges with low power consumption. In Europe the unlicensed 868MHz frequency band is used, such that anyone use LoRaWAN without the need to apply for dedicated spectrum. So LoRaWAN is a good choice for IoT applications.\nAround the globe there are several commercial network operators that operate LoRaWAN networks. These networks consist of gateways which provide coverage to connect nodes with the LoRaWAN network and a backend. The gateways forward messages to and from the nodes to the network operator backend via the Internet. In the backend messages received from the nodes can be accessed and data can be send to the nodes. Besides the commercial networks also the community driven The Things Network (TTN) provides a freely accessible LoRaWAN network in many locations worldwide. Here the gateways are provided and operated by individuals. Also the backend can be used by anyone free of charge.\nThis article explains how an own gateway can be built and connected to The Things Network. The following explanations are mainly based on a guide from the Zürich TTN community.\nGateway Hardware Gateways are either available as ready to use product my multiple network equipment vendors. An overview is on this page of the TTN community. But there is also the possibility to build an own gateway. This article focuses on the latter. There are multiple possibilities to build an own gateway, but in the following these components are used:\nRaspberry Pi (or any similar board with a SPI connection) iC880A-SPI - LoRaWAN Concentrator 868 MHz SMA Antenna and Pigtail Cable Additional components like a SD card, a power supply or a casing are not covered in the article. These should be suitable for the intended environment, e.g. outdoor placement of the gateway.\nDescriptioniC880a pinRaspberry Pi pinSupply Voltage 5V212GND226Reset1322SPI CLK1423SPI MISO1521SPI MOSI1619SPI CE1724\nSoftware The TTN network is currently in transition from the current Things Network Stack V2 to the next version, which is called The Things Stack V3. Therefore, the software required to operate an own gateway is not actively maintained anymore while the software for the next version is not yet available.\nThe guide of the TTN Zürich community also includes an automatic installation script. It was developed for an older version of Raspbian, but also works on current versions.\n","permalink":"https://www.cemocom.de/2020/12/12/building-a-lorawan-gateway/","summary":"\u003ch2 id=\"background\"\u003eBackground\u003c/h2\u003e\n\u003cp\u003eLong Range Wide Area Network (LoRaWAN) is a proprietary wireless communication protocol. While the achievable data rates are by design comparatively low, it offers long communication ranges with low power consumption. In Europe the unlicensed 868MHz frequency band is used, such that anyone use LoRaWAN without the need to apply for dedicated spectrum. So LoRaWAN is a good choice for IoT applications.\u003c/p\u003e\n\u003cp\u003eAround the globe there are several commercial network operators that operate LoRaWAN networks. These networks consist of gateways which provide coverage to connect nodes with the LoRaWAN network and a backend. The gateways forward messages to and from the nodes to the network operator backend via the Internet. In the backend messages received from the nodes can be accessed and data can be send to the nodes. Besides the commercial networks also the community driven \u003ca href=\"https://www.thethingsnetwork.org/\"\u003eThe Things Network\u003c/a\u003e (TTN) provides a freely accessible LoRaWAN network in many locations worldwide. Here the gateways are provided and operated by individuals. Also the backend can be used by anyone free of charge.\u003c/p\u003e","title":"Building a LoRaWAN Gateway"},{"content":"Background If you want to encrypt the root file system of a computer running Linux with LUKS, you usually have to entere the encryption password at every system boot. Especially in the case of a headless computer acting as a server this is not suitable. To overcome this problem LUKS offers the possibility to store the encryption key as a keyfile and use it to open the encrypted disk.\nThere also exist several guides how the keyfile can be stored on a USB stick. Examples include here, here or here (the second and third guides are only available in German).\nHowever, all the guides we found did not work with recent versions of Debian or Ubuntu. The problem seems to be a combination of systemd not supporting the keyscript mechanism used in some guides and incomplete support of keyfiles in the script /usr/share/initramfs-tools/hooks/cryptroot. The cryptroot script is responsible to generate the crypttab file in the initramfs which is used during the boot process to unlock the encrypted disks.\nSolution To overcome the problem we created a minimal hook that generates a correct crypttab file in the initramfs. The script is placed in /etc/initramfs-tools/hooks/xyz-crypttab. Thereby it is executed at the end of the process to generate an initramfs. The script looks as follows:\n#!/bin/sh PREREQ=\u0026#34;\u0026#34; prereqs() { echo \u0026#34;$PREREQ\u0026#34; } case \u0026#34;$1\u0026#34; in prereqs) prereqs exit 0 ;; esac . /usr/share/initramfs-tools/hook-functions . /lib/cryptsetup/functions TABFILE=\u0026#34;/etc/crypttab\u0026#34; cp \u0026#34;$TABFILE\u0026#34; \u0026#34;${DESTDIR}/cryptroot/crypttab\u0026#34; exit 0 The script simply copies the original crypttab file into the correct destination in the initramfs. After the scripted is set as executable, the existing initramfs can be regenerated by executing sudo update-initramfs -u. At the next boot your system should be able to unlock the encrypted root file system by the keyfile stored on the USB stick.\n","permalink":"https://www.cemocom.de/2020/04/15/open-luks-encrypted-device-via-key-on-usb-stick/","summary":"\u003ch2 id=\"background\"\u003eBackground\u003c/h2\u003e\n\u003cp\u003eIf you want to encrypt the root file system of a computer running Linux with LUKS, you usually have to entere the encryption password at every system boot. Especially in the case of a headless computer acting as a server this is not suitable. To overcome this problem LUKS offers the possibility to store the encryption key as a keyfile and use it to open the encrypted disk.\u003c/p\u003e\n\u003cp\u003eThere also exist several guides how the keyfile can be stored on a USB stick. Examples include \u003ca href=\"https://blog.tinned-software.net/automount-a-luks-encrypted-volume-on-system-start/\"\u003ehere\u003c/a\u003e, \u003ca href=\"https://decatec.de/linux/verschluesselte-festplatte-luks-mit-usb-stick-bei-systemstart-entschluesseln/\"\u003ehere\u003c/a\u003e or \u003ca href=\"https://wiki.debianforum.de/Cryptsetup_mit_systemd_und_Schl%C3%BCssel_auf_externem_USB-Stick\"\u003ehere\u003c/a\u003e (the second and third guides are only available in German).\u003c/p\u003e","title":"Open LUKS encrypted device via key on USB stick"},{"content":"Private Cellular Networks LTE and 5G based private cellular networks.\nsrsLTE https://www.srslte.com/\nOpen Air Interface https://www.openairinterface.org/\nLQID - LTE Quality Information Database Measurement of the quality of mobile networks using smartphone based apps. Show and evaluate the quality in a cloud based service.\n","permalink":"https://www.cemocom.de/services/mobile-networks/","summary":"\u003ch2 id=\"private-cellular-networks\"\u003ePrivate Cellular Networks\u003c/h2\u003e\n\u003cp\u003eLTE and 5G based private cellular networks.\u003c/p\u003e\n\u003ch3 id=\"srslte\"\u003esrsLTE\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"https://www.srslte.com/\"\u003ehttps://www.srslte.com/\u003c/a\u003e\u003c/p\u003e\n\u003ch3 id=\"open-air-interface\"\u003eOpen Air Interface\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"https://www.openairinterface.org/\"\u003ehttps://www.openairinterface.org/\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"lqid---lte-quality-information-database\"\u003eLQID - LTE Quality Information Database\u003c/h2\u003e\n\u003cp\u003eMeasurement of the quality of mobile networks using smartphone based apps. Show and evaluate the quality in a cloud based service.\u003c/p\u003e","title":"Mobile Networks"},{"content":"System level simulation of cellular mobile communication networks.\nSimulation Library Java based library for discrete event simulations. Fork of IKR SimLib.\nSimulation Control and Management Tooling for parameter studies and execution of simulations. Good match for simulators based on SimLib. An introduction of a scalable setup for simulation studies is provided in this article.\n","permalink":"https://www.cemocom.de/services/simulation/","summary":"\u003cp\u003eSystem level simulation of cellular mobile communication networks.\u003c/p\u003e\n\u003ch2 id=\"simulation-library\"\u003eSimulation Library\u003c/h2\u003e\n\u003cp\u003eJava based library for discrete event simulations. Fork of \u003ca href=\"https://www.ikr.uni-stuttgart.de/institute/infrastructure/ikr-simlib-object-oriented-simulation-library/\"\u003eIKR SimLib\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"simulation-control-and-management\"\u003eSimulation Control and Management\u003c/h2\u003e\n\u003cp\u003eTooling for parameter studies and execution of simulations. Good match for simulators based on SimLib. An introduction of a scalable setup for simulation studies is provided \u003ca href=\"/2021/06/21/scalable-setup-for-simulation-studies/\"\u003ein this article\u003c/a\u003e.\u003c/p\u003e","title":"Simulation"},{"content":"Impressum Angaben gemäß § 5 TMG Sebastian Scholz\nKontakt E-Mail: contact@cemocom.de\nHaftung für Inhalte Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.\nVerpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.\nHaftung für Links Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.\nUrheberrecht Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.\nSoweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.\nDatenschutzerklärung 1. Datenschutz auf einen Blick Allgemeine Hinweise Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen Daten passiert, wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit denen Sie persönlich identifiziert werden können. Ausführliche Informationen zum Thema Datenschutz entnehmen Sie unserer unter diesem Text aufgeführten Datenschutzerklärung.\nDatenerfassung auf dieser Website Wer ist verantwortlich für die Datenerfassung auf dieser Website? Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten können Sie dem Abschnitt „Hinweis zur Verantwortlichen Stelle“ in dieser Datenschutzerklärung entnehmen.\nWie erfassen wir Ihre Daten? Ihre Daten werden zum einen dadurch erhoben, dass Sie uns diese mitteilen. Hierbei kann es sich z. B. um Daten handeln, die Sie in ein Kontaktformular eingeben.\nAndere Daten werden automatisch oder nach Ihrer Einwilligung beim Besuch der Website durch unsere IT-Systeme erfasst. Das sind vor allem technische Daten (z. B. Internetbrowser, Betriebssystem oder Uhrzeit des Seitenaufrufs). Die Erfassung dieser Daten erfolgt automatisch, sobald Sie diese Website betreten.\nWofür nutzen wir Ihre Daten? Ein Teil der Daten wird erhoben, um eine fehlerfreie Bereitstellung der Website zu gewährleisten. Andere Daten können zur Analyse Ihres Nutzerverhaltens verwendet werden.\nWelche Rechte haben Sie bezüglich Ihrer Daten? Sie haben jederzeit das Recht, unentgeltlich Auskunft über Herkunft, Empfänger und Zweck Ihrer gespeicherten personenbezogenen Daten zu erhalten. Sie haben außerdem ein Recht, die Berichtigung oder Löschung dieser Daten zu verlangen. Wenn Sie eine Einwilligung zur Datenverarbeitung erteilt haben, können Sie diese Einwilligung jederzeit für die Zukunft widerrufen. Außerdem haben Sie das Recht, unter bestimmten Umständen die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen. Des Weiteren steht Ihnen ein Beschwerderecht bei der zuständigen Aufsichtsbehörde zu.\nHierzu sowie zu weiteren Fragen zum Thema Datenschutz können Sie sich jederzeit an uns wenden.\n2. Hosting und Content Delivery Networks (CDN) Externes Hosting Diese Website wird bei einem externen Dienstleister gehostet (Hoster). Die personenbezogenen Daten, die auf dieser Website erfasst werden, werden auf den Servern des Hosters gespeichert. Hierbei kann es sich v.a. um IP-Adressen, Kontaktanfragen, Meta- und Kommunikationsdaten, Vertragsdaten, Kontaktdaten, Namen, Websitezugriffe und sonstige Daten, die über eine Website generiert werden, handeln.\nDer Einsatz des Hosters erfolgt zum Zwecke der Vertragserfüllung gegenüber unseren potenziellen und bestehenden Kunden (Art. 6 Abs. 1 lit. b DSGVO) und im Interesse einer sicheren, schnellen und effizienten Bereitstellung unseres Online-Angebots durch einen professionellen Anbieter (Art. 6 Abs. 1 lit. f DSGVO).\nUnser Hoster wird Ihre Daten nur insoweit verarbeiten, wie dies zur Erfüllung seiner Leistungspflichten erforderlich ist und unsere Weisungen in Bezug auf diese Daten befolgen.\nWir setzen folgenden Hoster ein:\nContabo GmbH\nAschauer Straße 32a\n81549 München\n3. Allgemeine Hinweise und Pflichtinformationen Datenschutz Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.\nWenn Sie diese Website benutzen, werden verschiedene personenbezogene Daten erhoben. Personenbezogene Daten sind Daten, mit denen Sie persönlich identifiziert werden können. Die vorliegende Datenschutzerklärung erläutert, welche Daten wir erheben und wofür wir sie nutzen. Sie erläutert auch, wie und zu welchem Zweck das geschieht.\nWir weisen darauf hin, dass die Datenübertragung im Internet (z. B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich.\nHinweis zur verantwortlichen Stelle Die verantwortliche Stelle für die Datenverarbeitung auf dieser Website ist:\nSebastian Scholz\nE-Mail: contact@cemocom.de\nVerantwortliche Stelle ist die natürliche oder juristische Person, die allein oder gemeinsam mit anderen über die Zwecke und Mittel der Verarbeitung von personenbezogenen Daten (z. B. Namen, E-Mail-Adressen o. Ä.) entscheidet.\nSpeicherdauer Soweit innerhalb dieser Datenschutzerklärung keine speziellere Speicherdauer genannt wurde, verbleiben Ihre personenbezogenen Daten bei uns, bis der Zweck für die Datenverarbeitung entfällt. Wenn Sie ein berechtigtes Löschersuchen geltend machen oder eine Einwilligung zur Datenverarbeitung widerrufen, werden Ihre Daten gelöscht, sofern wir keinen anderen rechtlich zulässigen Gründe für die Speicherung Ihrer personenbezogenen Daten haben (z.B. steuer- oder handelsrechtliche Aufbewahrungsfristen); im letztgenannten Fall erfolgt die Löschung nach Fortfall dieser Gründe.\nWiderruf Ihrer Einwilligung zur Datenverarbeitung Viele Datenverarbeitungsvorgänge sind nur mit Ihrer ausdrücklichen Einwilligung möglich. Sie können eine bereits erteilte Einwilligung jederzeit widerrufen. Die Rechtmäßigkeit der bis zum Widerruf erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.\nWiderspruchsrecht gegen die Datenerhebung in besonderen Fällen sowie gegen Direktwerbung (Art. 21 DSGVO) WENN DIE DATENVERARBEITUNG AUF GRUNDLAGE VON ART. 6 ABS. 1 LIT. E ODER F DSGVO ERFOLGT, HABEN SIE JEDERZEIT DAS RECHT, AUS GRÜNDEN, DIE SICH AUS IHRER BESONDEREN SITUATION ERGEBEN, GEGEN DIE VERARBEITUNG IHRER PERSONENBEZOGENEN DATEN WIDERSPRUCH EINZULEGEN; DIES GILT AUCH FÜR EIN AUF DIESE BESTIMMUNGEN GESTÜTZTES PROFILING. DIE JEWEILIGE RECHTSGRUNDLAGE, AUF DENEN EINE VERARBEITUNG BERUHT, ENTNEHMEN SIE DIESER DATENSCHUTZERKLÄRUNG. WENN SIE WIDERSPRUCH EINLEGEN, WERDEN WIR IHRE BETROFFENEN PERSONENBEZOGENEN DATEN NICHT MEHR VERARBEITEN, ES SEI DENN, WIR KÖNNEN ZWINGENDE SCHUTZWÜRDIGE GRÜNDE FÜR DIE VERARBEITUNG NACHWEISEN, DIE IHRE INTERESSEN, RECHTE UND FREIHEITEN ÜBERWIEGEN ODER DIE VERARBEITUNG DIENT DER GELTENDMACHUNG, AUSÜBUNG ODER VERTEIDIGUNG VON RECHTSANSPRÜCHEN (WIDERSPRUCH NACH ART. 21 ABS. 1 DSGVO). WERDEN IHRE PERSONENBEZOGENEN DATEN VERARBEITET, UM DIREKTWERBUNG ZU BETREIBEN, SO HABEN SIE DAS RECHT, JEDERZEIT WIDERSPRUCH GEGEN DIE VERARBEITUNG SIE BETREFFENDER PERSONENBEZOGENER DATEN ZUM ZWECKE DERARTIGER WERBUNG EINZULEGEN; DIES GILT AUCH FÜR DAS PROFILING, SOWEIT ES MIT SOLCHER DIREKTWERBUNG IN VERBINDUNG STEHT. WENN SIE WIDERSPRECHEN, WERDEN IHRE PERSONENBEZOGENEN DATEN ANSCHLIESSEND NICHT MEHR ZUM ZWECKE DER DIREKTWERBUNG VERWENDET (WIDERSPRUCH NACH ART. 21 ABS. 2 DSGVO).\nBeschwerderecht bei der zuständigen Aufsichtsbehörde Im Falle von Verstößen gegen die DSGVO steht den Betroffenen ein Beschwerderecht bei einer Aufsichtsbehörde, insbesondere in dem Mitgliedstaat ihres gewöhnlichen Aufenthalts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen Verstoßes zu. Das Beschwerderecht besteht unbeschadet anderweitiger verwaltungsrechtlicher oder gerichtlicher Rechtsbehelfe.\nRecht auf Datenübertragbarkeit Sie haben das Recht, Daten, die wir auf Grundlage Ihrer Einwilligung oder in Erfüllung eines Vertrags automatisiert verarbeiten, an sich oder an einen Dritten in einem gängigen, maschinenlesbaren Format aushändigen zu lassen. Sofern Sie die direkte Übertragung der Daten an einen anderen Verantwortlichen verlangen, erfolgt dies nur, soweit es technisch machbar ist.\nSSL- bzw. TLS-Verschlüsselung Diese Seite nutzt aus Sicherheitsgründen und zum Schutz der Übertragung vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns als Seitenbetreiber senden, eine SSL- bzw. TLS- Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile des Browsers von „http://“ auf „https://“ wechselt und an dem Schloss-Symbol in Ihrer Browserzeile.\nWenn die SSL- bzw. TLS-Verschlüsselung aktiviert ist, können die Daten, die Sie an uns übermitteln, nicht von Dritten mitgelesen werden.\nAuskunft, Löschung und Berichtigung Sie haben im Rahmen der geltenden gesetzlichen Bestimmungen jederzeit das Recht auf unentgeltliche Auskunft über Ihre gespeicherten personenbezogenen Daten, deren Herkunft und Empfänger und den Zweck der Datenverarbeitung und ggf. ein Recht auf Berichtigung oder Löschung dieser Daten. Hierzu sowie zu weiteren Fragen zum Thema personenbezogene Daten können Sie sich jederzeit an uns wenden.\nRecht auf Einschränkung der Verarbeitung Sie haben das Recht, die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen. Hierzu können Sie sich jederzeit an uns wenden. Das Recht auf Einschränkung der Verarbeitung besteht in folgenden Fällen:\nWenn Sie die Richtigkeit Ihrer bei uns gespeicherten personenbezogenen Daten bestreiten, benötigen wir in der Regel Zeit, um dies zu überprüfen. Für die Dauer der Prüfung haben Sie das Recht, die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen. Wenn die Verarbeitung Ihrer personenbezogenen Daten unrechtmäßig geschah/geschieht, können Sie statt der Löschung die Einschränkung der Datenverarbeitung verlangen. Wenn wir Ihre personenbezogenen Daten nicht mehr benötigen, Sie sie jedoch zur Ausübung, Verteidigung oder Geltendmachung von Rechtsansprüchen benötigen, haben Sie das Recht, statt der Löschung die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen. Wenn Sie die Verarbeitung Ihrer personenbezogenen Daten eingeschränkt haben, dürfen diese Daten – von ihrer Speicherung abgesehen – nur mit Ihrer Einwilligung oder zur Geltendmachung, Ausübung oder Verteidigung von Rechtsansprüchen oder zum Schutz der Rechte einer anderen natürlichen oder juristischen Person oder aus Gründen eines wichtigen öffentlichen Interesses der Europäischen Union oder eines Mitgliedstaats verarbeitet werden.\nDatenerfassung auf dieser Website Cookies Unsere Internetseiten verwenden so genannte „Cookies“. Cookies sind kleine Textdateien und richten auf Ihrem Endgerät keinen Schaden an. Sie werden entweder vorübergehend für die Dauer einer Sitzung (Session-Cookies) oder dauerhaft (permanente Cookies) auf Ihrem Endgerät gespeichert. Session-Cookies werden nach Ende Ihres Besuchs automatisch gelöscht. Permanente Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese selbst löschen oder eine automatische Löschung durch Ihren Webbrowser erfolgt.\nTeilweise können auch Cookies von Drittunternehmen auf Ihrem Endgerät gespeichert werden, wenn Sie unsere Seite betreten (Third-Party-Cookies). Diese ermöglichen uns oder Ihnen die Nutzung bestimmter Dienstleistungen des Drittunternehmens (z.B. Cookies zur Abwicklung von Zahlungsdienstleistungen).\nCookies haben verschiedene Funktionen. Zahlreiche Cookies sind technisch notwendig, da bestimmte Websitefunktionen ohne diese nicht funktionieren würden (z.B. die Warenkorbfunktion oder die Anzeige von Videos). Andere Cookies dienen dazu, das Nutzerverhalten auszuwerten oder Werbung anzuzeigen.\nCookies, die zur Durchführung des elektronischen Kommunikationsvorgangs (notwendige Cookies) oder zur Bereitstellung bestimmter, von Ihnen erwünschter Funktionen (funktionale Cookies, z. B. für die Warenkorbfunktion) oder zur Optimierung der Website (z.B. Cookies zur Messung des Webpublikums) erforderlich sind, werden auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO gespeichert, sofern keine andere Rechtsgrundlage angegeben wird. Der Websitebetreiber hat ein berechtigtes Interesse an der Speicherung von Cookies zur technisch fehlerfreien und optimierten Bereitstellung seiner Dienste. Sofern eine Einwilligung zur Speicherung von Cookies abgefragt wurde, erfolgt die Speicherung der betreffenden Cookies ausschließlich auf Grundlage dieser Einwilligung (Art. 6 Abs. 1 lit. a DSGVO); die Einwilligung ist jederzeit widerrufbar.\nSie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browsers aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein.\nSoweit Cookies von Drittunternehmen oder zu Analysezwecken eingesetzt werden, werden wir Sie hierüber im Rahmen dieser Datenschutzerklärung gesondert informieren und ggf. eine Einwilligung abfragen.\nServer-Log-Dateien Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log-Dateien, die Ihr Browser automatisch an uns übermittelt. Dies sind:\nBrowsertyp und Browserversion verwendetes Betriebssystem Referrer URL Hostname des zugreifenden Rechners Uhrzeit der Serveranfrage IP-Adresse Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen.\nDie Erfassung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO. Der Websitebetreiber hat ein berechtigtes Interesse an der technisch fehlerfreien Darstellung und der Optimierung seiner Website – hierzu müssen die Server-Log-Files erfasst werden.\n","permalink":"https://www.cemocom.de/about/privacy-policy/","summary":"\u003ch2 id=\"impressum\"\u003eImpressum\u003c/h2\u003e\n\u003ch3 id=\"angaben-gemäß--5-tmg\"\u003eAngaben gemäß § 5 TMG\u003c/h3\u003e\n\u003cp\u003eSebastian Scholz\u003c/p\u003e\n\u003ch3 id=\"kontakt\"\u003eKontakt\u003c/h3\u003e\n\u003cp\u003eE-Mail: \u003ca href=\"mailto:contact@cemocom.de\"\u003econtact@cemocom.de\u003c/a\u003e\u003c/p\u003e\n\u003ch3 id=\"haftung-für-inhalte\"\u003eHaftung für Inhalte\u003c/h3\u003e\n\u003cp\u003eAls Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.\u003c/p\u003e\n\u003cp\u003eVerpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.\u003c/p\u003e","title":"Impressum \u0026 Datenschutzerklärung"}]