Commit 7e6be93195f889c3f6ef8959bee066448b71d4ec
1 parent
fe4b6547c6
Exists in
master
gateway commit
Showing 9 changed files with 773 additions and 0 deletions Inline Diff
gw_RPi3/README
| File was created | 1 | pi@192.168.1.180 : raspberry |
gw_RPi3/config.txt
| File was created | 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 |
gw_RPi3/python/Endpoint.py
| File was created | 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. |
gw_RPi3/python/gat.py
| File was created | 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) |
gw_RPi3/python/gate.py
| File was created | 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) |
gw_RPi3/python/gateway.py
| File was created | 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") |
gw_RPi3/python/gateway_http_downlink.py
| File was created | 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): |
gw_RPi3/python/gateway_http_uplink.py
| File was created | 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 |
gw_RPi3/python/test_gateway.py
| File was created | 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')) |