· 4 years ago · Aug 20, 2021, 09:54 AM
1local SECONDS_IN_MINUTE = 60
2local SECONDS_IN_HOUR = SECONDS_IN_MINUTE*60
3local cla = require("cla")
4local pretty = require("cc.pretty") or {pretty = function(...) return ... end, print = function(...) print("Using legacy print"); print(...) end}
5local modem = peripheral.find("modem")
6local request
7local hasInit
8modem.open(2500)
9
10local function convertReal(timeSeconds)
11 local hours = timeSeconds/SECONDS_IN_HOUR
12 local ticks = 0
13 if hours > 6 then
14 ticks = 0
15 local extrahours = hours - 6
16 ticks = ticks + extrahours*1000
17 else
18 ticks = 18000
19 ticks = ticks + hours*1000
20 end
21 return ticks
22end
23
24
25local function createOptions(options)
26 local returnString = ""
27 for key,value in pairs(options) do
28 if string.sub(returnString,1,1) == "?" then
29 returnString = returnString .. "&" .. textutils.urlEncode(key) .. "=" .. textutils.urlEncode(value)
30 else
31 returnString = returnString .. "?" .. textutils.urlEncode(key) .. "=" .. textutils.urlEncode(value)
32 end
33 end
34 return returnString
35end
36
37cla.Valueless("gemstone", "Enable Gemstone mode.")
38cla.String("location", nil, "Location of weather.")
39cla.Float("lat", nil, "Latitude of location.")
40cla.Float("lon", nil, "Longitude of location.")
41cla.String("key", nil, "API Key for OpenWeatherMap.")
42cla.Integer("offset", 0, "Offset of time. (in hours)")
43
44local parsedFlags = cla:Parse({...})
45
46local endpoint = "http://api.openweathermap.org/data/2.5/" -- Change this if you use OpenWeatherMap paid plans or something?
47
48local codes = {
49 [200] = function()
50 print("Updating to thunder...")
51 commands.weather("thunder")
52 end,
53 [300] = 500,
54 [500] = function()
55 print("Updating to rain...")
56 commands.weather("rain")
57 end,
58 [600] = 500,
59 [700] = {
60 [701] = function()
61 print("Updating to mist...")
62 end
63 },
64 [800] = function()
65 print("Updating to clear...")
66 commands.weather("clear")
67 end
68}
69
70local function codeHandler(rawcode)
71--print("poo")
72 local code = math.floor(rawcode/100)*100
73--print(code)
74 local function subcodeHandler(t, subcode)
75--pretty.print(pretty.pretty(t))
76 for subcode2,subvalue in pairs(t) do
77 if type(subvalue) == "number" and subcode2 == subcode then
78-- print("d")
79 subcodeHandler(t, subcode2)
80 elseif type(subvalue) == "function" and subcode2 == subcode then
81-- print("e")
82-- print(subcode, subcode2)
83 subvalue()
84 end
85 end
86 end
87 for code2,value in pairs(codes) do
88--print(code2, code)
89 if type(value) == "function" and code == code2 then
90-- print("a")
91 value()
92 elseif type(value) == "number" and code == code2 then
93-- print("b")
94 codeHandler(value)
95 elseif type(value) == "table" and code == code2 then
96-- print("c")
97 subcodeHandler(value,rawcode)
98 end
99 end
100
101end
102
103parallel.waitForAny(function()
104 print("Updating weather.")
105 while true do
106 local options
107 if parsedFlags.location.value then
108 options = {
109 ["q"] = parsedFlags.location.value
110 }
111 elseif parsedFlags.lat.value and parsedFlags.lon.value then
112 options = {
113 ["lat"] = parsedFlags.lat.value,
114 ["lon"] = parsedFlags.lon.value
115 }
116 else
117 error("Either lat/lon or location is required.")
118 end
119 options["appid"] = parsedFlags.key.value
120 local requestJSON,error = http.get(endpoint .. "weather" .. createOptions(options))
121 print("Got response.")
122 request = textutils.unserialiseJSON(requestJSON.readAll())
123 if error or not request.weather then
124 print("Uh oh, we got an error! heres some information for the developers: " .. error .. " | " .. pretty.print(pretty.pretty(request)))
125 end
126 print("Decoded response.")
127 requestJSON.close()
128 print("Closed handle.")
129-- print("Weather Code: " .. (pretty.print(pretty.pretty(request.weather))) or "Unknown")
130 codeHandler(request.weather[1].id)
131
132 print("Updated weather.")
133 pretty.print(pretty.pretty(request))
134 modem.transmit(2500, 2500, textutils.serialiseJSON({
135 ["iconType"] = request.weather[1].icon:sub(-1,-1),
136 ["icon"] = tonumber(request.weather[1].icon:sub(1,#request.weather[1].icon-1)),
137 ["main"] = request.weather[1].main,
138 ["description"] = (request.weather[1].description or request.weather[1].main),
139 ["speed"] = request.wind.speed,
140 ["deg"] = request.wind.deg
141 }))
142 hasInit = true
143 sleep(10*SECONDS_IN_MINUTE)
144 end
145end, function()
146 while true do
147---@diagnostic disable-next-line: undefined-field
148 local epoch = (os.epoch("utc")/1000) + parsedFlags.offset.value*SECONDS_IN_HOUR
149 commands.time("set", convertReal(epoch))
150 sleep(.25)
151 end
152end, function ()
153 while true do
154---@diagnostic disable-next-line: undefined-field
155 local _,_,channel,_,msg = os.pullEvent("modem_message")
156 if channel == 2500 and msg == "get" and hasInit then
157 modem.transmit(2500, 2500, textutils.serialiseJSON({
158 ["iconType"] = request.weather[1].icon:sub(-1,-1),
159 ["icon"] = tonumber(request.weather[1].icon:sub(1,#request.weather[1].icon-1)),
160 ["main"] = request.weather[1].main,
161 ["description"] = request.weather[1].description,
162 ["speed"] = request.wind.speed,
163 ["deg"] = request.wind.deg
164 }))
165 end
166 end
167end)