Skip to content

Commit 4369fe9

Browse files
committed
init
1 parent d707529 commit 4369fe9

File tree

9 files changed

+326
-1
lines changed

9 files changed

+326
-1
lines changed

.github/workflows/test.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Busted
2+
3+
4+
on: [push, pull_request]
5+
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: checkout
13+
uses: actions/checkout@v2
14+
with:
15+
submodules: true
16+
17+
- name: get lua
18+
uses: leafo/gh-actions-lua@v10
19+
with:
20+
luaVersion: "5.1"
21+
22+
- name: get luarocks
23+
uses: leafo/gh-actions-luarocks@v4
24+
with:
25+
luaVersion: "5.1"
26+
27+
- name: get busted and luasocket
28+
run: |
29+
luarocks install busted
30+
luarocks install luasocket
31+
luarocks install luasec
32+
33+
- name: fetch dependencies
34+
run: |
35+
chmod +x ./fetch-deps.sh
36+
./fetch-deps.sh
37+
38+
- name: test
39+
run: |
40+
busted tests

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/libs

.vscode/settings.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Lua.diagnostics.globals": [
3+
"describe",
4+
"before_each",
5+
"it",
6+
"xit",
7+
"pending"
8+
]
9+
}

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2025 Minecraft ComputerCraft Scripts
3+
Copyright (c) 2025 ChristophLHR
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

definitions.lua

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---@class MQTT_message
2+
---@field id? string | nil Will be set by the broker
3+
---@field payload? any Can be anything
4+
---@field maxReads? number Reads until deletion. Optional
5+
---@field sender number ComputerID of the message-sender
6+
---@field target? number[] Table of targetID's. Optional. If set, only target computers will receive message (IF SUBSCRIBED to topic!)
7+
---@field ttl? number Time to Live in Milliseconds. Default: 10 minutes, unless retain=true
8+
---@field retain? boolean Will always send first, even if subscribed after message was send. Only one per Topic!
9+
---@field timestamp? number will be set by the broker
10+
---@field readBy? table<number,boolean> will be managed by the broker
11+
12+
---@class MQTT_messages
13+
---@field [string] MQTT_message string => Topic
14+
15+
---@class MQTTBroker_Client
16+
---@field id number
17+
---@field timeoutDuration number Timeout in seconds - Overwritten in function "registerLastWillMessage"
18+
---@field lastSeen number Updated in any request the Client inits
19+
20+
---@class MQTTBroker_ClientList
21+
---@field clients MQTTBroker_Client[]
22+
23+
---@type MQTT_message
24+
local message;
25+
26+
---@type MQTT_messages
27+
local messages;

fetch-deps.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
3+
# ---- Whats happening ---- #
4+
5+
# This fetches the dependencies listed in the "libs" variable and saves them in the targetFolder
6+
7+
8+
9+
set -e
10+
11+
libs=(
12+
"helperFunctions-lib"
13+
"testSuite-lib"
14+
"eventHandler-lib"
15+
)
16+
17+
# Basic setup variables
18+
repo="mc-cc-scripts"
19+
branch="master"
20+
targetFolderName=libs
21+
22+
23+
# fetch files.txt and save each file into the targetFolder
24+
fetch() {
25+
files_txt=$(curl -fsSL "https://raw.githubusercontent.com/$repo/$1/$branch/files.txt")
26+
if [ -z "$files_txt" ]; then
27+
echo "Could not load files.txt for $1"
28+
exit 1
29+
fi
30+
while IFS= read -r FILE; do
31+
url="https://raw.githubusercontent.com/$repo/$1/$branch/$FILE"
32+
33+
mkdir -p "$(dirname "$targetFolderName/$FILE")" # create the folder (and subfolders specified in the files.txt)
34+
rm -f $targetFolderName/$FILE.lua # rm existing file
35+
if ! curl -s -o "$targetFolderName/$FILE" "$url"; then
36+
echo "could not get / write the file $i: '$FILE' to the folder '$targetFolderName'"
37+
exit 1
38+
fi
39+
# echo "saved $1: '$FILE' in '$targetFolderName'"
40+
done < <(echo "$files_txt")
41+
}
42+
43+
if [[ $# -eq 0 ]]; then
44+
# No arguments given, fetch all
45+
for i in "${libs[@]}"; do
46+
fetch "$i"
47+
done
48+
else
49+
# Argument given, fetch arguemt
50+
fetch "$1"
51+
fi

files.txt

Whitespace-only changes.

mqttBroker.lua

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---@class MQTTBroker
2+
local MQTTBroker = {}
3+
4+
local ERRORText = {
5+
["validate_MessageWrongType"] = "Message is not of type table! It is type %s",
6+
["validate_MissingSender"] = "Sender_ID is Missing",
7+
}
8+
9+
MQTTBroker.defaultTimeOut = 300 * 1000 -- 5 minutes
10+
11+
---@type MQTTBroker_ClientList
12+
MQTTBroker.clientList = {}
13+
14+
---@type nil | fun(topic, message): boolean, (nil | string)
15+
MQTTBroker.validator = nil
16+
17+
---@type MQTT_messages
18+
MQTTBroker.messages = {}
19+
20+
---@private
21+
MQTTBroker.messageIndex = {}
22+
23+
---@param id any
24+
---@return MQTT_message | nil
25+
function MQTTBroker:getMessageByID(id)
26+
return self.messageIndex[id]
27+
end
28+
29+
30+
31+
---@param topic string
32+
---@param message MQTT_message
33+
---@return boolean
34+
---@return string | nil
35+
function MQTTBroker:validatePayload(topic, message)
36+
if type(message) ~= "table" then
37+
return false, string.format(ERRORText["validate_MessageWrongType"], type(message))
38+
end
39+
if not message.sender or type(message.sender) ~= "number" then
40+
return false, ERRORText["validate_MissingSender"]
41+
end
42+
if not MQTTBroker.validator then return true end
43+
return MQTTBroker.validator(topic, message.payload)
44+
end
45+
46+
---@param topic string
47+
---@param message MQTT_message
48+
---@return boolean success
49+
---@return string | nil idOrErrorReason
50+
function MQTTBroker:publish(topic, message)
51+
local ok, err = self:validatePayload(topic, message)
52+
if not ok then
53+
return false, err
54+
end
55+
56+
57+
58+
local suffix = 0
59+
local isDublicate = true
60+
local currentTime = string.format(math.floor(os.time()))
61+
while isDublicate do
62+
if self:getMessageByID(currentTime .. suffix) then
63+
suffix = suffix + 1
64+
isDublicate = true
65+
else
66+
isDublicate = false
67+
end
68+
end
69+
message.id = currentTime .. suffix
70+
71+
if not message.retain and not message.ttl then
72+
message.ttl = self.defaultTimeOut
73+
end
74+
75+
message.readBy = {}
76+
77+
if self.messages[topic] == nil then
78+
self.messages[topic] = {}
79+
end
80+
81+
table.insert(self.messages[topic], message)
82+
self.messageIndex[message.id] = message
83+
return true, message.id
84+
end
85+
86+
---@param clientID number
87+
---@param topic string
88+
---@return boolean success
89+
function MQTTBroker:subscribe(clientID, topic)
90+
return true
91+
end
92+
93+
---@param clientID number
94+
---@param topic string
95+
---@return boolean success
96+
function MQTTBroker:unsubscribe(clientID, topic)
97+
return true
98+
end
99+
100+
---@param clientID number
101+
---@return MQTT_messages
102+
function MQTTBroker:getMessagesForClient(clientID)
103+
return {}
104+
end
105+
106+
107+
---@param clientID number
108+
---@param topic string
109+
---@return boolean success
110+
function MQTTBroker:markAsRead(clientID, topic)
111+
return true
112+
end
113+
114+
---@return number deletedMessages
115+
function MQTTBroker:expireMessages()
116+
return 0
117+
end
118+
119+
---@param topic string
120+
---@return boolean
121+
function MQTTBroker:pruneTopic(topic)
122+
return true
123+
end
124+
125+
---Register the last will of a client (In case of a timeout)
126+
---@param clientID number
127+
---@param topic string
128+
---@param message MQTT_message
129+
---@param timeoutDuration number in seconds
130+
---@return boolean
131+
function MQTTBroker:registerLastWillMessage(clientID, topic, message, timeoutDuration)
132+
return true
133+
end
134+
135+
---comment
136+
---@return integer
137+
function MQTTBroker:checkClientTimeouts()
138+
return 0
139+
end
140+
141+
142+
return MQTTBroker

tests/MQTTBroker_spec.lua

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---@class are
2+
---@field same function
3+
---@field equal function
4+
---@field equals function
5+
6+
---@class is
7+
---@field truthy function
8+
---@field falsy function
9+
---@field not_true function
10+
---@field not_false function
11+
12+
---@class has
13+
---@field error function
14+
---@field errors function
15+
16+
---@class assert
17+
---@field are are
18+
---@field is is
19+
---@field are_not are
20+
---@field is_not is
21+
---@field has has
22+
---@field has_no has
23+
---@field True function
24+
---@field False function
25+
---@field has_error function
26+
---@field is_false function
27+
---@field is_true function
28+
---@field equal function
29+
assert = assert
30+
31+
package.path = package.path .. ";"
32+
.."libs/?.lua;"
33+
.."libs/peripherals/?.lua;"
34+
35+
local MQTTBroker = require("mqttBroker")
36+
37+
describe("Basic Tests", function()
38+
it("loaded", function()
39+
assert.is.truthy(MQTTBroker)
40+
end)
41+
describe("Publish", function()
42+
it("SenderID", function ()
43+
assert.True(MQTTBroker:publish("test", {sender = 2}))
44+
assert.False(MQTTBroker:publish("test", {}))
45+
end)
46+
it("Publish", function()
47+
local ok, id = MQTTBroker:publish("test", {sender = 2, payload = "test payload"})
48+
local ok2, id2 = MQTTBroker:publish("test", {sender = 2, payload = "test payload 2"})
49+
assert.True(ok)
50+
assert.True(ok2)
51+
assert.are.same(MQTTBroker:getMessageByID(id).payload, "test payload")
52+
assert.are.same(MQTTBroker:getMessageByID(id2).payload, "test payload 2")
53+
end)
54+
end)
55+
end)

0 commit comments

Comments
 (0)