Two stage build to reduce image size and build improvements provided by @imrehg.
Add (optional) metering support for use with Prometheus.
This commit is contained in:
parent
e40d71b4a8
commit
2922f63a85
@ -1,18 +1,29 @@
|
|||||||
FROM resin/%%RESIN_MACHINE_NAME%%-buildpack-deps
|
FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest AS buildstep
|
||||||
|
|
||||||
# Enable systemd, as Resin requires this
|
|
||||||
ENV INITSYSTEM on
|
|
||||||
|
|
||||||
# Make the hardware type available as a runtime env var
|
|
||||||
ENV RESIN_ARCH %%RESIN_ARCH%%
|
|
||||||
ENV RESIN_MACHINE_NAME %%RESIN_MACHINE_NAME%%
|
|
||||||
|
|
||||||
# Copy the build and run environment
|
|
||||||
COPY . /opt/ttn-gateway/
|
|
||||||
WORKDIR /opt/ttn-gateway/
|
WORKDIR /opt/ttn-gateway/
|
||||||
|
|
||||||
# Build the gateway (or comment this out if debugging on-device)
|
# downloading utils
|
||||||
RUN ./dev/build.sh && rm -rf ./dev
|
RUN apt-get update && \
|
||||||
|
apt-get install wget build-essential libc6-dev git pkg-config protobuf-compiler libprotobuf-dev libprotoc-dev automake libtool autoconf python-dev python-rpi.gpio
|
||||||
|
|
||||||
# Start it up
|
COPY dev dev
|
||||||
CMD ["sh", "-c", "./run.py"]
|
RUN ./dev/build.sh
|
||||||
|
|
||||||
|
FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest
|
||||||
|
|
||||||
|
WORKDIR /opt/ttn-gateway
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install python-rpi.gpio && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY --from=buildstep /opt/ttn-gateway/mp_pkt_fwd .
|
||||||
|
COPY --from=buildstep /usr/local/lib/libpaho-embed-* /usr/lib/
|
||||||
|
COPY --from=buildstep /usr/lib/libttn* /usr/lib/
|
||||||
|
|
||||||
|
COPY run.py ./
|
||||||
|
COPY start.sh ./
|
||||||
|
|
||||||
|
# run when container lands on device
|
||||||
|
CMD ["bash", "start.sh"]
|
||||||
|
58
Dockerfile.template.metering
Normal file
58
Dockerfile.template.metering
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest AS buildstep
|
||||||
|
|
||||||
|
# downloading utils
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install wget build-essential libc6-dev git pkg-config protobuf-compiler libprotobuf-dev libprotoc-dev automake libtool autoconf python-dev python-rpi.gpio
|
||||||
|
|
||||||
|
WORKDIR /etc
|
||||||
|
|
||||||
|
# versions
|
||||||
|
ENV NODE_EXPORTER_VERSION 0.12.0
|
||||||
|
ENV DIST_ARCH linux-armv7
|
||||||
|
RUN wget https://github.com/prometheus/node_exporter/releases/download/${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH}.tar.gz \
|
||||||
|
&& tar xvfz node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH}.tar.gz \
|
||||||
|
&& rm node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH}.tar.gz
|
||||||
|
|
||||||
|
COPY gwexporter.tgz /opt/ttn-gateway/gwexporter.tgz
|
||||||
|
WORKDIR /opt/gwexporter
|
||||||
|
RUN tar xvzf /opt/ttn-gateway/gwexporter.tgz
|
||||||
|
RUN wget https://nodejs.org/dist/v8.8.1/node-v8.8.1-linux-armv6l.tar.gz \
|
||||||
|
&& tar xvzf node-v8.8.1-linux-armv6l.tar.gz \
|
||||||
|
&& mv node-v8.8.1-linux-armv6l/* . \
|
||||||
|
&& rm -rf node-v8.8.1-linux-armv6l
|
||||||
|
|
||||||
|
WORKDIR /opt/ttn-gateway/
|
||||||
|
COPY dev dev
|
||||||
|
RUN ./dev/build.sh
|
||||||
|
|
||||||
|
FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install python-rpi.gpio && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Enable systemd
|
||||||
|
ENV INITSYSTEM on
|
||||||
|
|
||||||
|
# versions
|
||||||
|
ENV NODE_EXPORTER_VERSION 0.12.0
|
||||||
|
ENV DIST_ARCH linux-armv7
|
||||||
|
|
||||||
|
WORKDIR /etc
|
||||||
|
COPY --from=buildstep /etc/node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH} .
|
||||||
|
|
||||||
|
WORKDIR /opt/gwexporter
|
||||||
|
COPY --from=buildstep /opt/gwexporter .
|
||||||
|
|
||||||
|
WORKDIR /opt/ttn-gateway
|
||||||
|
COPY --from=buildstep /opt/ttn-gateway/mp_pkt_fwd .
|
||||||
|
COPY --from=buildstep /usr/local/lib/libpaho-embed-* /usr/lib/
|
||||||
|
COPY --from=buildstep /usr/lib/libttn* /usr/lib/
|
||||||
|
COPY run.py run.py
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
COPY start.sh.metering start.sh
|
||||||
|
|
||||||
|
# run when container lands on device
|
||||||
|
CMD ["bash", "start.sh"]
|
21
README.md
21
README.md
@ -14,6 +14,7 @@ Currently any Raspberry Pi with one of the following gateway boards, communicati
|
|||||||
* [IMST iC880A-SPI](http://webshop.imst.de/ic880a-spi-lorawan-concentrator-868mhz.html). Preferable configured as described [by TTN-ZH](https://github.com/ttn-zh/ic880a-gateway/wiki). You **do not** need to follow the **Setting up the software** step, as the setup scripts in this repository does it for you.
|
* [IMST iC880A-SPI](http://webshop.imst.de/ic880a-spi-lorawan-concentrator-868mhz.html). Preferable configured as described [by TTN-ZH](https://github.com/ttn-zh/ic880a-gateway/wiki). You **do not** need to follow the **Setting up the software** step, as the setup scripts in this repository does it for you.
|
||||||
* [LinkLabs Raspberry Pi "Hat"](http://link-labs.myshopify.com/products/lorawan-raspberry-pi-board)
|
* [LinkLabs Raspberry Pi "Hat"](http://link-labs.myshopify.com/products/lorawan-raspberry-pi-board)
|
||||||
* [RisingHF IoT Dicovery](http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en)
|
* [RisingHF IoT Dicovery](http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en)
|
||||||
|
* [RAK831](http://www.rakwireless.com/en/WisKeyOSH/RAK831)
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ For a more complete list of possible environment variables, see [CONFIGURATION](
|
|||||||
|
|
||||||
### Device environment variables - no GPS
|
### Device environment variables - no GPS
|
||||||
|
|
||||||
For example, for an IMST iC880A with no GPS, the MINIMUM environment variables that you should configure at this screen should look something like this:
|
For example, for an IMST iC880A or RAK831 with no GPS, the MINIMUM environment variables that you should configure at this screen should look something like this:
|
||||||
|
|
||||||
Name | Value
|
Name | Value
|
||||||
------------------|--------------------------
|
------------------|--------------------------
|
||||||
@ -47,7 +48,7 @@ GW_ID | The gateway ID from the TTN console
|
|||||||
GW_KEY | The gateway KEY from the TTN console
|
GW_KEY | The gateway KEY from the TTN console
|
||||||
GW_RESET_PIN | 22 (optional)
|
GW_RESET_PIN | 22 (optional)
|
||||||
|
|
||||||
GW_RESET_PIN can be left out if you are using Gonzalo Casas' backplane board, or any other setup using pin 22 as reset pin. This is because pin 22 is the default reset pin used by this resin.io setup.
|
GW_RESET_PIN can be left out if you are using Gonzalo Casas' backplane board, the RAK backplane for the RAK831, or any other setup using pin 22 as reset pin. This is because pin 22 is the default reset pin used by this resin.io setup.
|
||||||
|
|
||||||
|
|
||||||
### Device environment variables - with GPS
|
### Device environment variables - with GPS
|
||||||
@ -77,6 +78,7 @@ Linklabs Rasberry Pi Hat<br />https://www.amazon.co.uk/868-MHz-LoRaWAN-RPi-Shiel
|
|||||||
Rising HF Board<br />http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en | 26
|
Rising HF Board<br />http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en | 26
|
||||||
IMST backplane or Lite gateway<br />https://wireless-solutions.de/products/long-range-radio/lora_lite_gateway.html | 29 (untested)
|
IMST backplane or Lite gateway<br />https://wireless-solutions.de/products/long-range-radio/lora_lite_gateway.html | 29 (untested)
|
||||||
Coredump backplane<br />https://github.com/dbrgn/ic880a-backplane/<br />https://shop.coredump.ch/product/ic880a-lorawan-gateway-backplane/ | 22
|
Coredump backplane<br />https://github.com/dbrgn/ic880a-backplane/<br />https://shop.coredump.ch/product/ic880a-lorawan-gateway-backplane/ | 22
|
||||||
|
RAK backplane<br /> | 11
|
||||||
|
|
||||||
|
|
||||||
If you get the message
|
If you get the message
|
||||||
@ -84,7 +86,7 @@ If you get the message
|
|||||||
after resin.io is finished downloading the application, or when restarting the gateway, it most likely means the `GW_RESET_PIN` you defined is incorrect. Alternatively the problem can be caused by the hardware, typically for the `IMST iC880A-SPI` board with insufficient voltage, try another power supply or slightly increase the voltage.
|
after resin.io is finished downloading the application, or when restarting the gateway, it most likely means the `GW_RESET_PIN` you defined is incorrect. Alternatively the problem can be caused by the hardware, typically for the `IMST iC880A-SPI` board with insufficient voltage, try another power supply or slightly increase the voltage.
|
||||||
|
|
||||||
|
|
||||||
## Special note for using the LinkLabs gateway on a Raspberry Pi 3
|
## Special note for using a Raspberry Pi 3
|
||||||
|
|
||||||
There is a backward incomatibility between the Raspberry Pi 1 and 2 hardware, and Raspberry Pi 3. For Raspberry Pi 3, it is necessary to make a small additional configuration change.
|
There is a backward incomatibility between the Raspberry Pi 1 and 2 hardware, and Raspberry Pi 3. For Raspberry Pi 3, it is necessary to make a small additional configuration change.
|
||||||
|
|
||||||
@ -156,11 +158,22 @@ If you get the error below please check if your ssh public key has been added to
|
|||||||
```
|
```
|
||||||
git add .
|
git add .
|
||||||
git commit -m "Updated gateway version"
|
git commit -m "Updated gateway version"
|
||||||
git push -f resin master"
|
git push -f resin master
|
||||||
```
|
```
|
||||||
|
|
||||||
- For devices without a GPS, the location that is configured on the TTN console is used. This location is only read at startup of the gateway. Therefore, after you set or changed the location, restart the application from the resin.io console.
|
- For devices without a GPS, the location that is configured on the TTN console is used. This location is only read at startup of the gateway. Therefore, after you set or changed the location, restart the application from the resin.io console.
|
||||||
|
|
||||||
|
# Device statistics
|
||||||
|
If you want to show nice looking statistics for your gateway(s) there are a couple of additional steps to take. First,
|
||||||
|
copy Dockerfile.template.metering to Dockerfile.template . Next copy start.sh.metering to start.sh . Now use the instructions above to
|
||||||
|
update the resin image.
|
||||||
|
|
||||||
|
Once the new image is deployed, go to the resin.io dashboard for your devices and select 'Enable Public device URL' in the drop down menu
|
||||||
|
(the one to the right of the light bulb). That is all that is required to provide metrics. Now you will need to install a metrics collector
|
||||||
|
on a seperate system as outlined in [Fleet-wide Machine Metrics Monitoring in 20mins](https://resin.io/blog/prometheusv2/)
|
||||||
|
|
||||||
|
(To show packet forwarder graphs you need to add your own graphs to the provided templates)
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
* [Gonzalo Casas](https://github.com/gonzalocasas) on the [iC880a-based gateway](https://github.com/ttn-zh/ic880a-gateway/tree/spi)
|
* [Gonzalo Casas](https://github.com/gonzalocasas) on the [iC880a-based gateway](https://github.com/ttn-zh/ic880a-gateway/tree/spi)
|
||||||
|
20
dev/build.sh
20
dev/build.sh
@ -5,17 +5,6 @@ INSTALL_DIR="/opt/ttn-gateway"
|
|||||||
mkdir -p $INSTALL_DIR/dev
|
mkdir -p $INSTALL_DIR/dev
|
||||||
cd $INSTALL_DIR/dev
|
cd $INSTALL_DIR/dev
|
||||||
|
|
||||||
if [ ! -d wiringPi ]; then
|
|
||||||
git clone git://git.drogon.net/wiringPi || { echo 'Cloning wiringPi failed.' ; exit 1; }
|
|
||||||
cd wiringPi
|
|
||||||
else
|
|
||||||
cd wiringPi
|
|
||||||
git reset --hard
|
|
||||||
git pull
|
|
||||||
fi
|
|
||||||
./build
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
if [ ! -d lora_gateway ]; then
|
if [ ! -d lora_gateway ]; then
|
||||||
git clone https://github.com/kersing/lora_gateway.git || { echo 'Cloning lora_gateway failed.' ; exit 1; }
|
git clone https://github.com/kersing/lora_gateway.git || { echo 'Cloning lora_gateway failed.' ; exit 1; }
|
||||||
else
|
else
|
||||||
@ -70,13 +59,10 @@ else
|
|||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get update
|
|
||||||
apt-get -y install protobuf-compiler libprotobuf-dev libprotoc-dev automake libtool autoconf python-dev python-rpi.gpio
|
|
||||||
|
|
||||||
cd $INSTALL_DIR/dev/lora_gateway/libloragw
|
cd $INSTALL_DIR/dev/lora_gateway/libloragw
|
||||||
sed -i -e 's/PLATFORM= .*$/PLATFORM= imst_rpi/g' library.cfg
|
sed -i -e 's/PLATFORM= .*$/PLATFORM= imst_rpi/g' library.cfg
|
||||||
sed -i -e 's/CFG_SPI= .*$/CFG_SPI= native/g' library.cfg
|
sed -i -e 's/CFG_SPI= .*$/CFG_SPI= native/g' library.cfg
|
||||||
make
|
make -j$(nproc)
|
||||||
|
|
||||||
cd $INSTALL_DIR/dev/protobuf-c
|
cd $INSTALL_DIR/dev/protobuf-c
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
@ -92,11 +78,11 @@ make install
|
|||||||
|
|
||||||
cd $INSTALL_DIR/dev/ttn-gateway-connector
|
cd $INSTALL_DIR/dev/ttn-gateway-connector
|
||||||
cp config.mk.in config.mk
|
cp config.mk.in config.mk
|
||||||
make
|
make -j$(nproc)
|
||||||
cp bin/libttn-gateway-connector.so /usr/lib/
|
cp bin/libttn-gateway-connector.so /usr/lib/
|
||||||
|
|
||||||
cd $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/
|
cd $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/
|
||||||
make
|
make -j$(nproc)
|
||||||
|
|
||||||
# Copy things needed at runtime to where they'll be expected
|
# Copy things needed at runtime to where they'll be expected
|
||||||
cp $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/mp_pkt_fwd $INSTALL_DIR/mp_pkt_fwd
|
cp $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/mp_pkt_fwd $INSTALL_DIR/mp_pkt_fwd
|
||||||
|
BIN
gwexporter.tgz
Normal file
BIN
gwexporter.tgz
Normal file
Binary file not shown.
7
run.py
7
run.py
@ -23,7 +23,7 @@ except RuntimeError:
|
|||||||
|
|
||||||
GWID_PREFIX="FFFE"
|
GWID_PREFIX="FFFE"
|
||||||
|
|
||||||
if not os.path.exists("mp_pkt_fwd"):
|
if not os.path.exists("/opt/ttn-gateway/mp_pkt_fwd"):
|
||||||
print ("ERROR: gateway executable not found. Is it built yet?")
|
print ("ERROR: gateway executable not found. Is it built yet?")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
@ -172,6 +172,7 @@ gateway_conf = {}
|
|||||||
gateway_conf['gateway_ID'] = my_eui
|
gateway_conf['gateway_ID'] = my_eui
|
||||||
gateway_conf['contact_email'] = os.getenv('GW_CONTACT_EMAIL', "")
|
gateway_conf['contact_email'] = os.getenv('GW_CONTACT_EMAIL', "")
|
||||||
gateway_conf['description'] = description
|
gateway_conf['description'] = description
|
||||||
|
gateway_conf['stat_file'] = 'loragwstat.json'
|
||||||
|
|
||||||
if(os.getenv('GW_FWD_CRC_ERR', "false")=="true"):
|
if(os.getenv('GW_FWD_CRC_ERR', "false")=="true"):
|
||||||
#default is False
|
#default is False
|
||||||
@ -291,7 +292,7 @@ if(os.getenv('SERVER_3_ENABLED', "false")=="true"):
|
|||||||
# We merge the json objects from the global_conf and local_conf and save it to the global_conf.
|
# We merge the json objects from the global_conf and local_conf and save it to the global_conf.
|
||||||
# Therefore there will not be a local_conf.json file.
|
# Therefore there will not be a local_conf.json file.
|
||||||
local_conf = {'SX1301_conf': sx1301_conf, 'gateway_conf': gateway_conf}
|
local_conf = {'SX1301_conf': sx1301_conf, 'gateway_conf': gateway_conf}
|
||||||
with open('global_conf.json', 'w') as the_file:
|
with open('/opt/ttn-gateway/global_conf.json', 'w') as the_file:
|
||||||
the_file.write(json.dumps(local_conf, indent=4))
|
the_file.write(json.dumps(local_conf, indent=4))
|
||||||
|
|
||||||
|
|
||||||
@ -332,5 +333,5 @@ while True:
|
|||||||
GPIO.cleanup(22)
|
GPIO.cleanup(22)
|
||||||
|
|
||||||
# Start forwarder
|
# Start forwarder
|
||||||
subprocess.call(["./mp_pkt_fwd"])
|
subprocess.call("/opt/ttn-gateway/mp_pkt_fwd -c /opt/ttn-gateway", shell=True)
|
||||||
time.sleep(15)
|
time.sleep(15)
|
||||||
|
15
start.sh.metering
Normal file
15
start.sh.metering
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Start the node exporter
|
||||||
|
mkdir /mnt/ramdisk
|
||||||
|
mount -t tmpfs -o size=8m tmpfs /mnt/ramdisk
|
||||||
|
cd /mnt/ramdisk
|
||||||
|
/opt/ttn-gateway/run.py &
|
||||||
|
|
||||||
|
# WORKAROUND: Add symlink, as gwexporter otherwise currently don't seem to find this file
|
||||||
|
ln -s /mnt/ramdisk/loragwstat.json /opt/gwexporter/loragwstat.json
|
||||||
|
|
||||||
|
export PATH=$PATH:/opt/gwexporter/bin
|
||||||
|
node /opt/gwexporter/gwexporter.js &
|
||||||
|
|
||||||
|
cd /etc && ./node_exporter -web.listen-address ":81"
|
Loading…
Reference in New Issue
Block a user