Compare commits
No commits in common. "8d63eb270b28346b353fc209d06b62790b9347f3" and "c10c3ec280cecb0058bcfd22b7a6980fee0ff696" have entirely different histories.
8d63eb270b
...
c10c3ec280
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/.venv
|
/node_modules
|
||||||
|
|
||||||
|
|
12
README.md
12
README.md
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
```text
|
```text
|
||||||
GET /api/ws
|
GET /api/ws
|
||||||
GET /api/cc/{uuid}/keypad/code
|
GET /api/{uuid}/keypad/code
|
||||||
GET /api/cc/{uuid}/keypad/get_user_info/{uid}
|
GET /api/{uuid}/keypad/get_user_info/{uid}
|
||||||
POST /api/cc/{uuid}/keypad/log/door_open/{uid}
|
POST /api/{uuid}/keypad/log/door_open/{uid}
|
||||||
POST /api/cc/{uuid}/keypad/set_code
|
POST /api/{uuid}/keypad/set_code
|
||||||
POST /api/cc/{uuid}/core/reboot
|
POST /api/{uuid}/core/reboot
|
||||||
POST /api/cc/{uuid}/core/update
|
POST /api/{uuid}/core/update
|
||||||
```
|
```
|
||||||
|
|
||||||
## websocket
|
## websocket
|
||||||
|
|
1533
package-lock.json
generated
Normal file
1533
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
package.json
Normal file
24
package.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "rtmc-be",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/knex": "^0.15.2",
|
||||||
|
"@types/node": "^22.5.0",
|
||||||
|
"@types/ws": "^8.5.12",
|
||||||
|
"typescript": "^5.5.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"knex": "^3.1.0",
|
||||||
|
"pug": "^3.0.3",
|
||||||
|
"ws": "^8.18.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
[tool.pylint.'MESSAGES CONTROL']
|
|
||||||
disable = [
|
|
||||||
"line-too-long",
|
|
||||||
"unnecessary-semicolon",
|
|
||||||
"trailing-newlines",
|
|
||||||
"missing-docstring"
|
|
||||||
]
|
|
||||||
|
|
113
server.py
113
server.py
|
@ -1,98 +1,47 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import string
|
|
||||||
import secrets
|
|
||||||
import json
|
import json
|
||||||
import websockets
|
from websockets import serve
|
||||||
|
|
||||||
clients = {
|
clients = {
|
||||||
"FD3ZJFHQ7r": {
|
"FD3ZJFHQ7r" : {
|
||||||
"doorOpen": False,
|
"doorOpen" : False,
|
||||||
"lockdown": False,
|
"lockdown" : False,
|
||||||
"lastOpened": 1, #unix timestamp
|
"lastOpened" : 1, #unix timestamp
|
||||||
"secLevel": 1,
|
"secLevel" : 1,
|
||||||
"openedBy": "user"
|
"openedBy" : "user"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def rand_id():
|
async def echo(websocket):
|
||||||
return ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(16))
|
print("Connection established")
|
||||||
|
authenticated = False
|
||||||
|
await websocket.send(json.dumps({
|
||||||
|
"type" : "SAuthReq"
|
||||||
|
}))
|
||||||
|
|
||||||
class WsClient:
|
async for msg in websocket:
|
||||||
def __init__(self, ws):
|
msg_json = json.loads(msg)
|
||||||
self.ws = ws
|
if authenticated == False:
|
||||||
self.module_info = {}
|
if msg_json["type"] == "CAuth":
|
||||||
self.pcid = None
|
if msg_json["token"] in clients:
|
||||||
|
await websocket.send(json.dumps({
|
||||||
def send(self, message):
|
"type" : "SAuthStatus",
|
||||||
self.ws.send(json.dumps(message))
|
"failed" : False,
|
||||||
|
"reason" : "Authentication Successful"
|
||||||
|
}))
|
||||||
|
authenticated = True
|
||||||
class WebSocketHandler:
|
else:
|
||||||
def __init__(self):
|
await websocket.send(json.dumps({
|
||||||
self.clients = {}
|
"type" : "SAuthStatus",
|
||||||
|
"failed" : True,
|
||||||
def on_message(self, client, message):
|
"reason" : "Invalid token"
|
||||||
message_type = message.get('type')
|
}))
|
||||||
|
|
||||||
# Route messages based on type using match-case
|
|
||||||
match message_type:
|
|
||||||
case "CAuth":
|
|
||||||
client.pcid = message["pcid"]
|
|
||||||
case "CLog":
|
|
||||||
print(f"[CC] [{message["level"]}] {message["msg"]}")
|
|
||||||
case "CModule":
|
|
||||||
match message["module"]:
|
|
||||||
case "keypad":
|
|
||||||
self.handle_keypad_msg(client, message["message"]);
|
|
||||||
|
|
||||||
def handle_keypad_msg(self, client: WsClient, message):
|
|
||||||
match message["type"]:
|
|
||||||
case "CDoorOpened":
|
|
||||||
print(f"[CC][KEYPAD] Door was opened on {message["time"]} {"manually" if message["manual"] else ""}")
|
|
||||||
case "CGetUserStat":
|
|
||||||
client.send({
|
|
||||||
"type": "SUserStat",
|
|
||||||
# user info
|
|
||||||
})
|
|
||||||
case "CGetDoorStat":
|
|
||||||
stats = {}
|
|
||||||
|
|
||||||
for pc in self.clients:
|
|
||||||
i = pc.module_info["keypad"]
|
|
||||||
stats[pc.uid] = i if i else {}
|
|
||||||
|
|
||||||
client.send({
|
|
||||||
"type": "CDoorStat",
|
|
||||||
"stats": stats
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def new_client(self, ws):
|
|
||||||
uid = rand_id()
|
|
||||||
self.clients[uid] = WsClient(ws)
|
|
||||||
|
|
||||||
self.clients[uid].send({
|
|
||||||
"type" : "SAuthReq"
|
|
||||||
})
|
|
||||||
|
|
||||||
async for msg_t in ws:
|
|
||||||
msg = json.loads(msg_t)
|
|
||||||
self.on_message(self.clients[uid], msg)
|
|
||||||
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
for c in self.clients:
|
|
||||||
c.ws.close()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
wsh = WebSocketHandler()
|
async with serve(echo, "localhost", 8765):
|
||||||
|
|
||||||
async with websockets.serve(wsh.new_client, "localhost", 8765):
|
|
||||||
await asyncio.get_running_loop().create_future()
|
await asyncio.get_running_loop().create_future()
|
||||||
|
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
0
src/index.ts
Normal file
0
src/index.ts
Normal file
21
tsconfig.json
Normal file
21
tsconfig.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"typeRoots": ["./node_modules/@types", "./src/types"],
|
||||||
|
"strict": true,
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"types": [""],
|
||||||
|
"noEmit": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"outDir": "build",
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user