Compare View
Commits (2)
Diff
Showing 13 changed files Side-by-side Diff
- ep_RPi4/README
- ep_RPi4/RasPi-Si5351
- ep_RPi4/cmdline.txt
- ep_RPi4/config.txt
- gw_RPi3/README
- gw_RPi3/config.txt
- gw_RPi3/python/Endpoint.py
- gw_RPi3/python/gat.py
- gw_RPi3/python/gate.py
- gw_RPi3/python/gateway.py
- gw_RPi3/python/gateway_http_downlink.py
- gw_RPi3/python/gateway_http_uplink.py
- gw_RPi3/python/test_gateway.py
ep_RPi4/README
... | ... | @@ -0,0 +1 @@ |
1 | +root@192.168.1.168: root |
ep_RPi4/cmdline.txt
... | ... | @@ -0,0 +1 @@ |
1 | +root=/dev/mmcblk0p2 rootwait console=tty1 console=ttyAMA0,115200 |
ep_RPi4/config.txt
... | ... | @@ -0,0 +1,39 @@ |
1 | +# Please note that this is only a sample, we recommend you to change it to fit | |
2 | +# your needs. | |
3 | +# You should override this file using a post-build script. | |
4 | +# See http://buildroot.org/manual.html#rootfs-custom | |
5 | +# and http://elinux.org/RPiconfig for a description of config.txt syntax | |
6 | + | |
7 | +# We always use the same names, the real used variant is selected by | |
8 | +# BR2_PACKAGE_RPI_FIRMWARE_{DEFAULT,X,CD} choice | |
9 | +start_file=start.elf | |
10 | +fixup_file=fixup.dat | |
11 | + | |
12 | +kernel=Image | |
13 | + | |
14 | +# To use an external initramfs file | |
15 | +#initramfs rootfs.cpio.gz | |
16 | + | |
17 | +# Disable overscan assuming the display supports displaying the full resolution | |
18 | +# If the text shown on the screen disappears off the edge, comment this out | |
19 | +disable_overscan=1 | |
20 | + | |
21 | +# How much memory in MB to assign to the GPU on Pi models having | |
22 | +# 256, 512 or 1024 MB total memory | |
23 | +gpu_mem_256=100 | |
24 | +gpu_mem_512=100 | |
25 | +gpu_mem_1024=100 | |
26 | + | |
27 | +# fixes rpi (3B, 3B+, 3A+, 4B and Zero W) ttyAMA0 serial console | |
28 | +dtoverlay=miniuart-bt | |
29 | + | |
30 | +# enable 64bits support | |
31 | +arm_64bit=1 | |
32 | + | |
33 | +dtparam=spi=on | |
34 | +# dtoverlay=spi0-1cs | |
35 | + | |
36 | +dtoverlay=i2c1 | |
37 | +dtparam=i2c_arm=on | |
38 | +dtparam=spi=on | |
39 | +dtparam=i2c1=on, dtparam=i2c_arm_baudrate=100000 |
gw_RPi3/README
... | ... | @@ -0,0 +1 @@ |
1 | +pi@192.168.1.180 : raspberry |
gw_RPi3/config.txt
... | ... | @@ -0,0 +1,59 @@ |
1 | +# For more options and information see | |
2 | +# http://rpf.io/configtxt | |
3 | +# Some settings may impact device functionality. See link above for details | |
4 | + | |
5 | +# uncomment if you get no picture on HDMI for a default "safe" mode | |
6 | +#hdmi_safe=1 | |
7 | + | |
8 | +# uncomment this if your display has a black border of unused pixels visible | |
9 | +# and your display can output without overscan | |
10 | +#disable_overscan=1 | |
11 | + | |
12 | +# uncomment the following to adjust overscan. Use positive numbers if console | |
13 | +# goes off screen, and negative if there is too much border | |
14 | +#overscan_left=16 | |
15 | +#overscan_right=16 | |
16 | +#overscan_top=16 | |
17 | +#overscan_bottom=16 | |
18 | + | |
19 | +# uncomment to force a console size. By default it will be display's size minus | |
20 | +# overscan. | |
21 | +#framebuffer_width=1280 | |
22 | +#framebuffer_height=720 | |
23 | + | |
24 | +# uncomment if hdmi display is not detected and composite is being output | |
25 | +#hdmi_force_hotplug=1 | |
26 | + | |
27 | +# uncomment to force a specific HDMI mode (this will force VGA) | |
28 | +#hdmi_group=1 | |
29 | +#hdmi_mode=1 | |
30 | + | |
31 | +# uncomment to force a HDMI mode rather than DVI. This can make audio work in | |
32 | +# DMT (computer monitor) modes | |
33 | +#hdmi_drive=2 | |
34 | + | |
35 | +# uncomment to increase signal to HDMI, if you have interference, blanking, or | |
36 | +# no display | |
37 | +#config_hdmi_boost=4 | |
38 | + | |
39 | +# uncomment for composite PAL | |
40 | +#sdtv_mode=2 | |
41 | + | |
42 | +#uncomment to overclock the arm. 700 MHz is the default. | |
43 | +#arm_freq=800 | |
44 | + | |
45 | +# Uncomment some or all of these to enable the optional hardware interfaces | |
46 | +dtparam=i2c_arm=on | |
47 | +#dtparam=i2s=on | |
48 | +dtparam=spi=on | |
49 | +dtparam=i2c1=on, dtparam=i2c_arm_baudrate=100000 | |
50 | + | |
51 | +# Uncomment this to enable the lirc-rpi module | |
52 | +#dtoverlay=lirc-rpi | |
53 | + | |
54 | +# Additional overlays and parameters are documented /boot/overlays/README | |
55 | + | |
56 | +# Enable audio (loads snd_bcm2835) | |
57 | +dtparam=audio=on | |
58 | +dtoverlay=disable-bt | |
59 | +dtoverlay=i2c1 |
gw_RPi3/python/Endpoint.py
... | ... | @@ -0,0 +1,32 @@ |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Created on Wed Jun 9 11:15:10 2021 | |
5 | + | |
6 | +@author: Georges de Massol | |
7 | +""" | |
8 | +import base64 | |
9 | +#import binascii | |
10 | + | |
11 | +class Endpoint: | |
12 | + def __init__(self, EUI = None): | |
13 | + """ | |
14 | + | |
15 | + Parameters | |
16 | + ---------- | |
17 | + EUI : bytes | |
18 | + ex : bytes([0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]) | |
19 | + | |
20 | + Returns | |
21 | + ------- | |
22 | + None. | |
23 | + | |
24 | + """ | |
25 | + # This must point to the API interface. | |
26 | + self.EUI = EUI | |
27 | + | |
28 | + #EUI = bytes([0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]) | |
29 | + def EUIfromjson(self, json): | |
30 | + self.EUI = base64.b64decode(json["devEUI"]).hex() | |
31 | + return self.EUI | |
32 | + | |
0 | 33 | \ No newline at end of file |
gw_RPi3/python/gat.py
... | ... | @@ -0,0 +1,124 @@ |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Do not execute directly. | |
5 | +Please execute gateway_http_uplink.py | |
6 | + | |
7 | +Created on Mon Oct 19 2021 | |
8 | + | |
9 | +@author: ALKADRI Mohammad | |
10 | +""" | |
11 | + | |
12 | +from gateway_http_downlink import Downlink | |
13 | + | |
14 | +from Endpoint import Endpoint | |
15 | + | |
16 | +import time | |
17 | +from datetime import datetime | |
18 | +import os | |
19 | +import json | |
20 | +import base64 | |
21 | + | |
22 | + | |
23 | +APIKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlfa2V5X2lkIjoiYzA2ZGY1MDMtNjE5Zi00ZjI2LTgxNzEtYTU0OTRmMWJmYmRmIiwiYXVkIjoiYXMiLCJpc3MiOiJhcyIsIm5iZiI6MTYyMjY1MzMzMSwic3ViIjoiYXBpX2tleSJ9.23eLyvgd5zheP9hDM0acCAl9ojhQjLTZAU77IKqhvQY' | |
24 | +server = 'localhost:8080' | |
25 | +#just defining an instance to be used | |
26 | +downlink = Downlink(server, APIKey) | |
27 | +directory = '/home/pi/python/' | |
28 | + | |
29 | + | |
30 | + | |
31 | +def WriteFile(body, event): | |
32 | + filename = directory + "log/" + \ | |
33 | + time.strftime("%Y_%m_%d_%H-%M-%S") + '_' + event | |
34 | + # in case of unexisting folder 'log' | |
35 | + if not os.path.exists(directory + 'log'): | |
36 | + os.mkdir(directory + 'log') | |
37 | + # in case of already existing file : | |
38 | + if os.path.exists(filename + ".json"): | |
39 | + i = 2 | |
40 | + while(os.path.exists(filename + '_' + str(i) + ".json")): | |
41 | + i += 1 | |
42 | + path = filename + '_' + str(i) + ".json" | |
43 | + else: | |
44 | + path = filename + ".json" | |
45 | + | |
46 | + f = open(path, "a") | |
47 | + f.write(body.decode("utf-8")) | |
48 | + f.close() | |
49 | + print("file written : %s" % path) | |
50 | + | |
51 | + | |
52 | +def step0(endpoint): | |
53 | + downlink.FlushQueue(endpoint.EUI) | |
54 | + downlink.Lorasend(endpoint.EUI, b'\x46') | |
55 | + print("State: The data sent by Gateway") | |
56 | + | |
57 | + | |
58 | +def step1(endpoint): | |
59 | + T3 = 222333 | |
60 | + T4 = 1112223 | |
61 | + print ("T3 : %s" % T3.to_bytes(4, 'big')) | |
62 | + print ("T4 : %s" % T4.to_bytes(4, 'big')) | |
63 | + T = T4 << 32| T3 | |
64 | + print ("T : %s" % T) | |
65 | + print ("T : %s" % T.to_bytes(8, 'big')) | |
66 | + downlink.FlushQueue(endpoint.EUI) | |
67 | + # send all data | |
68 | + downlink.Lorasend(endpoint.EUI, T.to_bytes(8, 'big')) | |
69 | + | |
70 | + | |
71 | +def reset(endpoint): | |
72 | + downlink.FlushQueue(endpoint.EUI) | |
73 | + downlink.Lorasend(endpoint.EUI, b'\x55') #initialisation packet | |
74 | + print("enpoint reset : %s" % endpoint.EUI) | |
75 | + | |
76 | + | |
77 | +def postcompute(event, body, Tn): | |
78 | + global data | |
79 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
80 | + | |
81 | + json_ = json.loads(body) | |
82 | + endpoint = Endpoint() | |
83 | + endpoint.EUIfromjson(json_) | |
84 | + | |
85 | + print("request from :\nEUI : %s" % endpoint.EUI) | |
86 | + print("name : %s" % json_['deviceName']) | |
87 | + # write json in a file | |
88 | + WriteFile(body, event) | |
89 | + | |
90 | + print("event : %s " % event) | |
91 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
92 | + #treat all cases | |
93 | + if event == 'up': | |
94 | + #b64 to bytes | |
95 | + data = base64.b64decode(json_["data"]) | |
96 | + #bytes to integer | |
97 | + #integer = int.from_bytes(data, 'big') | |
98 | + print("data received from Endpoint : ") | |
99 | + print("base 64 : %s" % json_["data"]) | |
100 | + print("bytes : %s" % data) | |
101 | + #print("int : %s" % integer) | |
102 | + print() | |
103 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
104 | + data = int.from_bytes(data, 'big') | |
105 | + print("data : %s" % data) | |
106 | + print("fin") | |
107 | + elif event == 'txack': | |
108 | + print("data : %s" % data) | |
109 | + if data == 0x5374617274 : # 0x5374617274 : Start | |
110 | + step0(endpoint) | |
111 | + elif data == 0x54696D6573: # 0x54696D6573 : Times | |
112 | + step1(endpoint) | |
113 | + else: | |
114 | + print("error : uncovered State") | |
115 | + reset(endpoint) | |
116 | + elif event == 'error': | |
117 | + print('error : ' + json_["error"]) | |
118 | + else: | |
119 | + print("possible error : uncovered event") | |
120 | + print(body) | |
121 | + reset(endpoint) | |
122 | + print() | |
123 | + | |
124 | +print("Chirpstack server for downlink : %s" % downlink.server) |
gw_RPi3/python/gate.py
... | ... | @@ -0,0 +1,165 @@ |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Do not execute directly. | |
5 | +Please execute gateway_http_downlink.py | |
6 | + | |
7 | +Created on Tue Jun 8 16:37:22 2021 | |
8 | + | |
9 | +@author: Georges de Massol | |
10 | +""" | |
11 | + | |
12 | +from gateway_http_downlink import Downlink | |
13 | + | |
14 | +from Endpoint import Endpoint | |
15 | + | |
16 | +import time | |
17 | +from datetime import datetime | |
18 | +import os | |
19 | +import json | |
20 | +import base64 | |
21 | + | |
22 | + | |
23 | + | |
24 | +APIKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlfa2V5X2lkIjoiYzA2ZGY1MDMtNjE5Zi00ZjI2LTgxNzEtYTU0OTRmMWJmYmRmIiwiYXVkIjoiYXMiLCJpc3MiOiJhcyIsIm5iZiI6MTYyMjY1MzMzMSwic3ViIjoiYXBpX2tleSJ9.23eLyvgd5zheP9hDM0acCAl9ojhQjLTZAU77IKqhvQY' | |
25 | +server = 'localhost:8080' | |
26 | +#just defining an instance to be used | |
27 | +downlink = Downlink(server, APIKey) | |
28 | +directory = '/home/pi/python/' | |
29 | + | |
30 | + | |
31 | +State = 0 | |
32 | + | |
33 | +def WriteFile(body, event): | |
34 | + filename = directory + "log/" + \ | |
35 | + time.strftime("%Y_%m_%d_%H-%M-%S") + '_' + event | |
36 | + # in case of unexisting folder 'log' | |
37 | + if not os.path.exists(directory + 'log'): | |
38 | + os.mkdir(directory + 'log') | |
39 | + # in case of already existing file : | |
40 | + if os.path.exists(filename + ".json"): | |
41 | + i = 2 | |
42 | + while(os.path.exists(filename + '_' + str(i) + ".json")): | |
43 | + i += 1 | |
44 | + path = filename + '_' + str(i) + ".json" | |
45 | + else: | |
46 | + path = filename + ".json" | |
47 | + | |
48 | + f = open(path, "a") | |
49 | + f.write(body.decode("utf-8")) | |
50 | + f.close() | |
51 | + print("file written : %s" % path) | |
52 | + | |
53 | + | |
54 | +def step0(Tn, endpoint): | |
55 | + global T2, State | |
56 | + print("Last State sss : %s" % State) | |
57 | + if State != 0: | |
58 | + print("probable error : message unexpected :") | |
59 | + print("Last State sss : %s" % State) | |
60 | + print("Current State : 0") | |
61 | + #reset() | |
62 | + T2 = Tn | |
63 | + State = 0 | |
64 | + | |
65 | +def step1(data, endpoint): | |
66 | + global T3, State, dTg | |
67 | + T3 = data | |
68 | + State = 1 | |
69 | + | |
70 | + #time spent by gateway between uplink and downlink | |
71 | + dTg = T3+1 | |
72 | + print ("Tg : %s" % dTg.to_bytes(4, 'big')) | |
73 | + downlink.FlushQueue(endpoint.EUI) | |
74 | + # send all data for step 3 | |
75 | + downlink.Lorasend(endpoint.EUI, b'\x01' + dTg.to_bytes(4, 'big')) | |
76 | + | |
77 | +def step2(endpoint, data): | |
78 | + global State | |
79 | + | |
80 | + if State != 1: | |
81 | + print("probable error : message unexpected :") | |
82 | + print("Last State : %s" % State) | |
83 | + print("Current State : 2") | |
84 | + reset() | |
85 | + | |
86 | + State = 2 | |
87 | + | |
88 | + dTe = int.from_bytes(data, 'big') | |
89 | + dTv = (dTe - dTg)/2 | |
90 | + print("time of flight (samples number) : %s" % dTv) | |
91 | + print("time of flight (microseconds) : %s" % (dTv * 0.0005)) ## 1 sample = 500ns | |
92 | + | |
93 | +def step3(endpoint): | |
94 | + global State | |
95 | + State = 3 | |
96 | + | |
97 | + #reset the endpoint | |
98 | + reset(endpoint) | |
99 | + | |
100 | +def reset(endpoint): | |
101 | + global State | |
102 | + downlink.FlushQueue(endpoint.EUI) | |
103 | + downlink.Lorasend(endpoint.EUI, b'\x55')#initialisation packet | |
104 | + print("enpoint reset : %s" % endpoint.EUI) | |
105 | + State = 0 | |
106 | +def postcompute(event, body, Tn): | |
107 | + print("D") | |
108 | + global data | |
109 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
110 | + | |
111 | + json_ = json.loads(body) | |
112 | + endpoint = Endpoint() | |
113 | + endpoint.EUIfromjson(json_) | |
114 | + | |
115 | + print("request from :\nEUI : %s" % endpoint.EUI) | |
116 | + print("name : %s" % json_['deviceName']) | |
117 | + # write json in a file | |
118 | + WriteFile(body, event) | |
119 | + | |
120 | + | |
121 | + print("event : %s " % event) | |
122 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
123 | + #treat all cases | |
124 | + if event == 'up': | |
125 | + #b64 to bytes | |
126 | + data = base64.b64decode(json_["data"]) | |
127 | + #bytes to integer | |
128 | + integer = int.from_bytes(data, 'big') | |
129 | + print("data received from Endpoint : ") | |
130 | + print("base 64 : %s" % json_["data"]) | |
131 | + print("bytes : %s" % data) | |
132 | + print("int : %s" % integer) | |
133 | + print() | |
134 | + | |
135 | + step = data[0] | |
136 | + print("step : %s" % step) | |
137 | + print("data : %s" % data[1:]) | |
138 | + if step == 0: | |
139 | + step0(Tn, endpoint) | |
140 | + elif step == 2: | |
141 | + step2(endpoint, data[1:]) | |
142 | + else: | |
143 | + print("error : uncovered step : %s" % step) | |
144 | + reset(endpoint) | |
145 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
146 | + data = int.from_bytes(data, 'big') | |
147 | + print("fin") | |
148 | + elif event == 'txack': | |
149 | + print("data sent to endpoint") | |
150 | + if State == 0: | |
151 | + step1(data, endpoint) | |
152 | + elif State == 2: | |
153 | + step3(endpoint) | |
154 | + else: | |
155 | + print('error : state %s not expected', State) | |
156 | + reset(endpoint) | |
157 | + | |
158 | + elif event == 'error': | |
159 | + print('error : ' + json_["error"]) | |
160 | + else: | |
161 | + print("possible error : uncovered event") | |
162 | + print(body) | |
163 | + reset(endpoint) | |
164 | + print() | |
165 | +print("Chirpstack server for downlink : %s" % downlink.server) |
gw_RPi3/python/gateway.py
... | ... | @@ -0,0 +1,199 @@ |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Do not execute directly. | |
5 | +Please execute gateway_http_downlink.py | |
6 | + | |
7 | +Created on Tue Jun 8 16:37:22 2021 | |
8 | + | |
9 | +@author: Georges de Massol | |
10 | +""" | |
11 | + | |
12 | +from gateway_http_downlink import Downlink | |
13 | + | |
14 | +from Endpoint import Endpoint | |
15 | + | |
16 | +import time | |
17 | +from datetime import datetime | |
18 | +import os | |
19 | +import json | |
20 | +import base64 | |
21 | + | |
22 | + | |
23 | +APIKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlfa2V5X2lkIjoiYzA2ZGY1MDMtNjE5Zi00ZjI2LTgxNzEtYTU0OTRmMWJmYmRmIiwiYXVkIjoiYXMiLCJpc3MiOiJhcyIsIm5iZiI6MTYyMjY1MzMzMSwic3ViIjoiYXBpX2tleSJ9.23eLyvgd5zheP9hDM0acCAl9ojhQjLTZAU77IKqhvQY' | |
24 | +server = 'localhost:8080' | |
25 | +#just defining an instance to be used | |
26 | +downlink = Downlink(server, APIKey) | |
27 | +directory = '/home/pi/python/' | |
28 | + | |
29 | + | |
30 | +State = 0 | |
31 | + | |
32 | +def WriteFile(body, event): | |
33 | + filename = directory + "log/" + \ | |
34 | + time.strftime("%Y_%m_%d_%H-%M-%S") + '_' + event | |
35 | + # in case of unexisting folder 'log' | |
36 | + if not os.path.exists(directory + 'log'): | |
37 | + os.mkdir(directory + 'log') | |
38 | + # in case of already existing file : | |
39 | + if os.path.exists(filename + ".json"): | |
40 | + i = 2 | |
41 | + while(os.path.exists(filename + '_' + str(i) + ".json")): | |
42 | + i += 1 | |
43 | + path = filename + '_' + str(i) + ".json" | |
44 | + else: | |
45 | + path = filename + ".json" | |
46 | + | |
47 | + f = open(path, "a") | |
48 | + f.write(body.decode("utf-8")) | |
49 | + f.close() | |
50 | + print("file written : %s" % path) | |
51 | + | |
52 | + | |
53 | +def step0(Tn, endpoint): | |
54 | + global T2, State | |
55 | + | |
56 | + print("Last State sss : %s" % State) | |
57 | + if State != 0: | |
58 | + print("probable error : message unexpected :") | |
59 | + print("Last State sss : %s" % State) | |
60 | + print("Current State : 0") | |
61 | + #reset() | |
62 | + T2 = Tn | |
63 | + State = 0 | |
64 | + | |
65 | +State=0 | |
66 | +dTg=0 | |
67 | +T3=0 | |
68 | + | |
69 | +def step1(data, endpoint): | |
70 | + global T3, State, dTg | |
71 | + T3 = data | |
72 | + State = 1 | |
73 | + | |
74 | + #time spent by gateway between uplink and downlink | |
75 | + dTg = T3+1 | |
76 | + print ("Tg : %s" % dTg.to_bytes(4, 'big')) | |
77 | + downlink.FlushQueue(endpoint.EUI) | |
78 | + # send all data for step 3 | |
79 | + downlink.Lorasend(endpoint.EUI, b'\x01' + dTg.to_bytes(7, 'big')) | |
80 | + | |
81 | + | |
82 | + | |
83 | +def step2(endpoint, data): | |
84 | + global State, dTg | |
85 | + | |
86 | + if State != 1: | |
87 | + print("probable error : message unexpected :") | |
88 | + print("Last State : %s" % State) | |
89 | + print("Current State : 2") | |
90 | + reset(endpoint) | |
91 | + | |
92 | + State = 2 | |
93 | + | |
94 | + dTe = int.from_bytes(data, 'big') | |
95 | + dTv = (dTe - dTg)/2 | |
96 | + print("time of flight (samples number) : %s" % dTv) | |
97 | + print("time of flight (microseconds) : %s" % (dTv * 0.0005)) ## 1 sample = 500ns | |
98 | + | |
99 | +def step3(endpoint): | |
100 | + global State | |
101 | + State = 3 | |
102 | + | |
103 | + #reset the endpoint | |
104 | + reset(endpoint) | |
105 | + | |
106 | +def reset(endpoint): | |
107 | + global State | |
108 | + downlink.FlushQueue(endpoint.EUI) | |
109 | + downlink.Lorasend(endpoint.EUI, b'\x55')#initialisation packet | |
110 | + print("enpoint reset : %s" % endpoint.EUI) | |
111 | + State = 0 | |
112 | +def postcompute(event, body, Tn): | |
113 | + print("D") | |
114 | + global data | |
115 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
116 | + | |
117 | + json_ = json.loads(body) | |
118 | + endpoint = Endpoint() | |
119 | + endpoint.EUIfromjson(json_) | |
120 | + | |
121 | + print("request from :\nEUI : %s" % endpoint.EUI) | |
122 | + print("name : %s" % json_['deviceName']) | |
123 | + # write json in a file | |
124 | + WriteFile(body, event) | |
125 | + | |
126 | + print("event : %s " % event) | |
127 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
128 | + #treat all cases | |
129 | + if event == 'up': | |
130 | + #b64 to bytes | |
131 | + data = base64.b64decode(json_["data"]) | |
132 | + #bytes to integer | |
133 | + integer = int.from_bytes(data, 'big') | |
134 | + print("data received from Endpoint : ") | |
135 | + print("base 64 : %s" % json_["data"]) | |
136 | + print("bytes : %s" % data) | |
137 | + print("int : %s" % integer) | |
138 | + print() | |
139 | + | |
140 | + step = data[0] | |
141 | + print("step : %s" % step) | |
142 | + print("data : %s" % data[1:]) | |
143 | + if step == 0: | |
144 | + step0(Tn, endpoint) | |
145 | + elif step == 2: | |
146 | + step2(endpoint, data[1:]) | |
147 | + else: | |
148 | + print("error : uncovered step : %s" % step) | |
149 | + reset(endpoint) | |
150 | + """ | |
151 | + print("preparation des donnees pour envoi a la prochaine connection du EndNode") | |
152 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
153 | + print("message pour : %s" % endpoint.EUI) | |
154 | + print("message int : %s" % integer) | |
155 | + #send a LoRa packet | |
156 | + fCnt = downlink.Lorasend(endpoint.EUI, data) | |
157 | + # Print the downlink frame-counter value. | |
158 | + print("fCnt : %s" % fCnt) | |
159 | + """ | |
160 | + | |
161 | + print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) | |
162 | + data = int.from_bytes(data, 'big') | |
163 | + print("fin") | |
164 | + elif event == 'txack': | |
165 | + print("data sent to endpoint") | |
166 | + if State == 0: | |
167 | + step1(data, endpoint) | |
168 | + elif State == 2: | |
169 | + step3(endpoint) | |
170 | + else: | |
171 | + print('error : state %s not expected', State) | |
172 | + reset(endpoint) | |
173 | + | |
174 | + elif event == 'error': | |
175 | + print('error : ' + json_["error"]) | |
176 | + else: | |
177 | + print("possible error : uncovered event") | |
178 | + print(body) | |
179 | + reset(endpoint) | |
180 | + print() | |
181 | + | |
182 | + | |
183 | + | |
184 | +# def start(): | |
185 | +# ok = False | |
186 | +# while not ok: | |
187 | +# try: | |
188 | +# Time = time.time() | |
189 | +# fCnt = downlink.Lorasend("70b3d549966002e1", Time) | |
190 | +# print(fCnt) | |
191 | +# time.sleep(5) | |
192 | +# ok = True | |
193 | +# except: | |
194 | +# pass | |
195 | +# | |
196 | +# start() | |
197 | + | |
198 | +#print ("Chirpstack API Key :\n%s" % downlink.api_token) | |
199 | +print("Chirpstack server for downlink : %s" % downlink.server) |
gw_RPi3/python/gateway_http_downlink.py
... | ... | @@ -0,0 +1,95 @@ |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Created on Tue Jun 8 16:03:39 2021 | |
5 | + | |
6 | +@author: Georges de Massol | |
7 | +""" | |
8 | +import grpc | |
9 | +from chirpstack_api.as_pb.external import api | |
10 | + | |
11 | +class Downlink: | |
12 | + def __init__(self, server = "localhost:8080", api_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlfa2V5X2lkIjoiYzA2ZGY1MDMtNjE5Zi00ZjI2LTgxNzEtYTU0OTRmMWJmYmRmIiwiYXVkIjoiYXMiLCJpc3MiOiJhcyIsIm5iZiI6MTYyMjY1MzMzMSwic3ViIjoiYXBpX2tleSJ9.23eLyvgd5zheP9hDM0acCAl9ojhQjLTZAU77IKqhvQY'): | |
13 | + """ | |
14 | + | |
15 | + Parameters | |
16 | + ---------- | |
17 | + server : string, optional | |
18 | + Chirpstack server adress, with port. The default is "localhost:8080". | |
19 | + api_token : TYPE, optional | |
20 | + Chirpstack API token. | |
21 | + | |
22 | + Returns | |
23 | + ------- | |
24 | + None. | |
25 | + | |
26 | + """ | |
27 | + # This must point to the API interface. | |
28 | + self.server = server | |
29 | + | |
30 | + # The DevEUI for which you want to enqueue the downlink. | |
31 | + #dev_eui = bytes([0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]) | |
32 | + | |
33 | + # The API token (retrieved using the web-interface). | |
34 | + self.api_token = api_token | |
35 | + | |
36 | + def Lorasend(self, dev_eui, data): | |
37 | + """ | |
38 | + | |
39 | + Parameters | |
40 | + ---------- | |
41 | + dev_eui : hex | |
42 | + The DevEUI for which you want to enqueue the downlink. | |
43 | + data : bytes | |
44 | + Data to be sent to the endpoint. | |
45 | + | |
46 | + Returns | |
47 | + ------- | |
48 | + fCnt : int | |
49 | + Downlink frame-counter value. | |
50 | + | |
51 | + """ | |
52 | + # Connect without using TLS. | |
53 | + channel = grpc.insecure_channel(self.server) | |
54 | + | |
55 | + # Device-queue API client. | |
56 | + client = api.DeviceQueueServiceStub(channel) | |
57 | + | |
58 | + # Define the API key meta-data. | |
59 | + auth_token = [("authorization", "Bearer %s" % self.api_token)] | |
60 | + | |
61 | + # Construct request. | |
62 | + req = api.EnqueueDeviceQueueItemRequest() | |
63 | + req.device_queue_item.confirmed = False | |
64 | + req.device_queue_item.data = bytes(data) | |
65 | + req.device_queue_item.dev_eui = dev_eui | |
66 | + req.device_queue_item.f_port = 10 | |
67 | + | |
68 | + resp = client.Enqueue(req, metadata=auth_token) | |
69 | + | |
70 | + return resp.f_cnt | |
71 | + def FlushQueue(self, dev_eui): | |
72 | + """ | |
73 | + Flush the downlink queue of an endpoint. | |
74 | + | |
75 | + Parameters | |
76 | + ---------- | |
77 | + dev_eui : hex | |
78 | + Endpoint EUI. | |
79 | + | |
80 | + """ | |
81 | + # Connect without using TLS. | |
82 | + channel = grpc.insecure_channel(self.server) | |
83 | + | |
84 | + # Device-queue API client. | |
85 | + client = api.DeviceQueueServiceStub(channel) | |
86 | + | |
87 | + # Define the API key meta-data. | |
88 | + auth_token = [("authorization", "Bearer %s" % self.api_token)] | |
89 | + | |
90 | + | |
91 | + req = api.FlushDeviceQueueRequest() | |
92 | + req.dev_eui = dev_eui | |
93 | + | |
94 | + client.Flush(req, metadata=auth_token) | |
95 | + | |
0 | 96 | \ No newline at end of file |
gw_RPi3/python/gateway_http_uplink.py
... | ... | @@ -0,0 +1,75 @@ |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Script to be executed. | |
5 | +Open a http server with function serve_forever(port) | |
6 | + | |
7 | +Created on Wed Jun 9 10:56:11 2021 | |
8 | + | |
9 | +@author: Georges de Massol | |
10 | +""" | |
11 | + | |
12 | + | |
13 | + | |
14 | +from http.server import HTTPServer, BaseHTTPRequestHandler | |
15 | +import urllib.parse | |
16 | +import gateway | |
17 | +import test_gateway | |
18 | +import gat | |
19 | +ip = 'localhost' | |
20 | + | |
21 | +class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): | |
22 | + def do_GET(self): | |
23 | + self.send_response(200) | |
24 | + self.end_headers() | |
25 | + self.wfile.write(b'Serveur uplink en marche!') | |
26 | + print("do_get") | |
27 | + | |
28 | + def do_POST(self): | |
29 | + print("do_post00") | |
30 | + | |
31 | + # ↓↓↓ Lecture de la dernière valeur de GNU Radio ↓↓↓ | |
32 | + # la lecture est faite le plus tôt possible pour éviter tout parasitage par un autre appareil. | |
33 | + | |
34 | + # Tn : échantillon n | |
35 | + Tn = 123456 | |
36 | + # ↑↑↑ Lecture de la dernière valeur de GNU Radio ↑↑↑ | |
37 | + content_length = int(self.headers['Content-Length']) | |
38 | + body = self.rfile.read(content_length) | |
39 | + self.send_response(200) | |
40 | + self.end_headers() | |
41 | + print(urllib.parse.urlparse(self.path)) | |
42 | + print("do_post0") | |
43 | + # print(urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)) | |
44 | + event = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query).get('event', None)[0] | |
45 | + print("do_post1") | |
46 | + gat.postcompute(event, body, Tn) | |
47 | + print("do_post2") | |
48 | + | |
49 | +def serve_forever(port = 6666): | |
50 | + """ | |
51 | + Function executed permanently. | |
52 | + Do not run code after this function. | |
53 | + | |
54 | + Parameters | |
55 | + ---------- | |
56 | + port : int, optional | |
57 | + Port for the server. The default is 6666. | |
58 | + | |
59 | + Returns | |
60 | + ------- | |
61 | + None. | |
62 | + | |
63 | + """ | |
64 | + print("d1") | |
65 | + | |
66 | + httpd = HTTPServer((ip, port), SimpleHTTPRequestHandler) | |
67 | + print("d2") | |
68 | + print("http server for uplink started on {}:{}\n".format(ip, port)) | |
69 | + print("d3") | |
70 | + httpd.serve_forever() | |
71 | + print("d4") | |
72 | + | |
73 | + | |
74 | +#do not add code then | |
75 | +serve_forever() |
gw_RPi3/python/test_gateway.py
... | ... | @@ -0,0 +1,23 @@ |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | + | |
5 | +Code de test pour envoyer des requetes au gateway. | |
6 | + | |
7 | +Created on Fri Jun 11 09:12:11 2021 | |
8 | + | |
9 | +@author: Georges de Massol | |
10 | +""" | |
11 | + | |
12 | +import gateway as gw | |
13 | + | |
14 | +gw.server = '192.168.1.180:8080' | |
15 | +EUI = "70b3d549966002e1" | |
16 | +endpoint = gw.Endpoint(EUI) | |
17 | +downlink = gw.Downlink(gw.server, gw.APIKey) | |
18 | +#fCnt = downlink.Lorasend(endpoint.EUI, b'\x01' + int(10000).to_bytes(4, 'big')) | |
19 | +downlink.FlushQueue(endpoint.EUI) | |
20 | +print("queue flushed") | |
21 | +fCnt = downlink.Lorasend(endpoint.EUI, b'\x55') | |
22 | +print("premier paquet envoye, fCnT : %s" % fCnt) | |
23 | +#downlink.ResetCounter(endpoint.EUI) |