-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbloomskyStructure.go
402 lines (336 loc) · 12.2 KB
/
bloomskyStructure.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
// Package bloomskyStructure calls rest API Bloomsky, puts it in the structure and gives somes functions
package bloomskyStructure
//go:generate echo Go Generate!
//go:generate ./command/bindata.sh
import (
"encoding/json"
"io/ioutil"
"math"
"os"
"time"
http "github.com/patrickalin/http-go"
"github.com/sirupsen/logrus"
)
const (
logFile = "bloomskyapi.log"
mockFile = "mock/mock.json"
)
var (
log *logrus.Logger
rest http.HTTP
mockFileByte []byte
)
type bloomsky struct {
url string
token string
BloomskyStructure BloomskyStructure
mock bool
}
// BloomskyStructure represents the structure of the JSON return by the API
type BloomskyStructure struct {
UTC float64 `json:"UTC"`
CityName string `json:"CityName"`
Storm BloomskyStormStructure `json:"Storm"`
Searchable bool `json:"Searchable"`
DeviceName string `json:"DeviceName"`
RegisterTime float64 `json:"RegisterTime"`
DST float64 `json:"DST"`
BoundedPoint string `json:"BoundedPoint"`
LON float64 `json:"LON"`
Point interface{} `json:"Point"`
VideoList []string `json:"VideoList"`
VideoListC []string `json:"VideoList_C"`
DeviceID string `json:"DeviceID"`
NumOfFollowers float64 `json:"NumOfFollowers"`
LAT float64 `json:"LAT"`
ALT float64 `json:"ALT"`
Data BloomskyDataStructure `json:"Data"`
FullAddress string `json:"FullAddress"`
StreetName string `json:"StreetName"`
PreviewImageList []string `json:"PreviewImageList"`
LastCall string
}
// BloomskyStormStructure represents the structure STORM of the JSON return by the API
type BloomskyStormStructure struct {
UVIndex string `json:"UVIndex"`
WindDirection interface{} `json:"WindDirection,int"`
WindGust float64 `json:"WindGust"`
WindGustms float64
WindGustkmh float64
SustainedWindSpeed float64 `json:"SustainedWindSpeed"`
SustainedWindSpeedms float64
SustainedWindSpeedkmh float64
Rain float64
RainDaily float64 `json:"RainDaily"`
RainDailymm float64
RainRate float64 `json:"RainRate"`
RainRatemm float64
Rainin float64 `json:"24hRain"`
Rainmm float64
}
// BloomskyDataStructure represents the structure SKY of the JSON return by the API
type BloomskyDataStructure struct {
Luminance float64 `json:"Luminance"`
TemperatureF float64 `json:"Temperature"`
TemperatureC float64
ImageURL string `json:"ImageURL"`
TS float64 `json:"TS"`
Rain bool `json:"Rain"`
Humidity float64 `json:"Humidity"`
Pressure float64 `json:"Pressure"`
Pressurehpa float64
DeviceType string `json:"DeviceType"`
Voltage float64 `json:"Voltage"`
Night bool `json:"Night"`
UVIndex float64 `json:"UVIndex"`
ImageTS float64 `json:"ImageTS"`
}
// Bloomsky is the interface BloomskyStructure
type Bloomsky interface {
GetDeviceID() string
GetHumidity() float64
GetCity() string
GetNumOfFollowers() int
GetPressureHPa() float64
GetWindDirection() string
GetWindDirectionDeg() int
GetTimeStamp() time.Time
GetIndexUV() string
GetTemperatureFahrenheit() float64
GetTemperatureCelsius() float64
GetPressureInHg() float64
GetWindGustMph() float64
GetWindGustMs() float64
GetSustainedWindSpeedMs() float64
GetSustainedWindSpeedMph() float64
GetRainDailyIn() float64
GetRainRateIn() float64
GetRainIn() float64
GetRainDailyMm() float64
GetRainRateMm() float64
GetWindGustkmh() float64
GetSustainedWindSpeedkmh() float64
GetRainMm() float64
GetBloomskyStruct() BloomskyStructure
GetLastCall() string
GetTS() float64
IsRain() bool
IsNight() bool
Refresh()
RefreshFromBody(body []byte)
}
// New calls bloomsky and get structurebloomsky
func New(bloomskyURL, bloomskyToken string, mock bool, l *logrus.Logger) Bloomsky {
initLog(l)
logDebug(funcName(), "New bloomsky structure", bloomskyURL)
// Read mock file
if mock {
logWarn(funcName(), "Mock activated !!!")
mockFileByte = readFile(mockFile)
}
rest = http.New(log)
return &bloomsky{url: bloomskyURL, token: bloomskyToken, mock: mock}
}
func (bloomsky *bloomsky) Refresh() {
if bloomsky.mock {
bloomsky.RefreshFromBody(mockFileByte)
return
}
bloomsky.refreshFromRest()
}
func (bloomsky *bloomsky) GetBloomskyStruct() BloomskyStructure {
return bloomsky.BloomskyStructure
}
//GetTimeStamp returns the timestamp give by Bloomsky
func (bloomsky *bloomsky) GetTimeStamp() time.Time {
return time.Unix(int64(bloomsky.BloomskyStructure.Data.TS), 0)
}
//GetCity returns the city name
func (bloomsky *bloomsky) GetCity() string {
return bloomsky.BloomskyStructure.CityName
}
//GetDeviceID returns the Device Id
func (bloomsky *bloomsky) GetDeviceID() string {
return bloomsky.BloomskyStructure.DeviceID
}
//GetNumOfFollowers returns the number of followers
func (bloomsky *bloomsky) GetNumOfFollowers() int {
return int(bloomsky.BloomskyStructure.NumOfFollowers)
}
//GetIndexUV returns the UV index from 1 to 11
func (bloomsky *bloomsky) GetIndexUV() string {
return bloomsky.BloomskyStructure.Storm.UVIndex
}
//IsNight returns true if it's the night
func (bloomsky *bloomsky) IsNight() bool {
return bloomsky.BloomskyStructure.Data.Night
}
//GetTemperatureFahrenheit returns temperature in Fahrenheit
func (bloomsky *bloomsky) GetTemperatureFahrenheit() float64 {
return bloomsky.BloomskyStructure.Data.TemperatureF
}
//GetTemperatureCelsius returns temperature in Celsius
func (bloomsky *bloomsky) GetTemperatureCelsius() float64 {
return bloomsky.BloomskyStructure.Data.TemperatureC
}
//GetHumidity returns humidity %
func (bloomsky *bloomsky) GetHumidity() float64 {
return bloomsky.BloomskyStructure.Data.Humidity
}
//GetPressureHPa returns pressure in HPa
func (bloomsky *bloomsky) GetPressureHPa() float64 {
return bloomsky.BloomskyStructure.Data.Pressurehpa
}
//GetPressureInHg returns pressure in InHg
func (bloomsky *bloomsky) GetPressureInHg() float64 {
return bloomsky.BloomskyStructure.Data.Pressure
}
//GetWindDirection returns wind direction (N,S,W,E, ...)
func (bloomsky *bloomsky) GetWindDirection() string {
switch bloomsky.BloomskyStructure.Storm.WindDirection.(type) {
case string:
return bloomsky.BloomskyStructure.Storm.WindDirection.(string)
default:
return "Unknow"
}
}
//GetWindDirectionDeg returns wind direction as dagrees (0,90,180,270, ...)
func (bloomsky *bloomsky) GetWindDirectionDeg() int {
cardinals := make(map[string]int)
cardinals["N"] = 0
cardinals["NE"] = 45
cardinals["E"] = 90
cardinals["SE"] = 135
cardinals["S"] = 180
cardinals["SW"] = 225
cardinals["W"] = 270
cardinals["NW"] = 315
switch bloomsky.BloomskyStructure.Storm.WindDirection.(type) {
case string:
return cardinals[bloomsky.BloomskyStructure.Storm.WindDirection.(string)]
default:
return 9999
}
}
//GetWindGustMph returns Wind in Mph
func (bloomsky *bloomsky) GetWindGustMph() float64 {
return bloomsky.BloomskyStructure.Storm.WindGust
}
//GetWindGustMs returns Wind in Ms
func (bloomsky *bloomsky) GetWindGustMs() float64 {
return (bloomsky.BloomskyStructure.Storm.WindGust * 1.61)
}
//GetSustainedWindSpeedMph returns Sustained Wind Speed in Mph
func (bloomsky *bloomsky) GetSustainedWindSpeedMph() float64 {
return bloomsky.BloomskyStructure.Storm.SustainedWindSpeed
}
//GetSustainedWindSpeedMs returns Sustained Wind Speed in Ms
func (bloomsky *bloomsky) GetSustainedWindSpeedMs() float64 {
return (bloomsky.BloomskyStructure.Storm.SustainedWindSpeed * 1.61)
}
//IsRain returns true if it's rain
func (bloomsky *bloomsky) IsRain() bool {
return bloomsky.BloomskyStructure.Data.Rain
}
//GetRainDailyIn returns rain daily in In
func (bloomsky *bloomsky) GetRainDailyIn() float64 {
return bloomsky.BloomskyStructure.Storm.RainDaily
}
//GetRainIn returns total rain in In
func (bloomsky *bloomsky) GetRainIn() float64 {
return bloomsky.BloomskyStructure.Storm.Rainin
}
//GetRainRateIn returns rain in In
func (bloomsky *bloomsky) GetRainRateIn() float64 {
return bloomsky.BloomskyStructure.Storm.RainRate
}
//GetRainDailyMm returns rain daily in mm
func (bloomsky *bloomsky) GetRainDailyMm() float64 {
return bloomsky.BloomskyStructure.Storm.RainDaily
}
//GetRainMm returns total rain in mm
func (bloomsky *bloomsky) GetRainMm() float64 {
return bloomsky.BloomskyStructure.Storm.Rainmm
}
//GetRainRateMm returns rain in mm
func (bloomsky *bloomsky) GetRainRateMm() float64 {
return bloomsky.BloomskyStructure.Storm.RainRate
}
//GetSustainedWindSpeedkmh returns Sustained Wind in Km/h
func (bloomsky *bloomsky) GetSustainedWindSpeedkmh() float64 {
return bloomsky.BloomskyStructure.Storm.SustainedWindSpeedkmh
}
//GetWindGustkmh returns Wind in Km/h
func (bloomsky *bloomsky) GetWindGustkmh() float64 {
return bloomsky.BloomskyStructure.Storm.WindGustkmh
}
func (bloomsky *bloomsky) GetLastCall() string {
return bloomsky.BloomskyStructure.LastCall
}
func (bloomsky *bloomsky) GetTS() float64 {
return bloomsky.BloomskyStructure.Data.TS
}
/* Func private ------------------------------------ */
//Init the logger
func initLog(l *logrus.Logger) {
if l != nil {
log = l
logDebug(funcName(), "Use the logger pass in New")
return
}
log = logrus.New()
logDebug(funcName(), "Create new logger")
log.Formatter = new(logrus.TextFormatter)
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY, 0666)
checkErr(err, funcName(), "Failed to log to file, using default stderr")
log.Out = file
}
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num*output)) / output
}
//Read file and return []byte
func readFile(fileName string) []byte {
fileByte, err := ioutil.ReadFile(fileName)
checkErr(err, funcName(), "Error reading the file", fileName)
return fileByte
}
//Call rest and refresh the structure
func (bloomsky *bloomsky) refreshFromRest() {
tock := []string{bloomsky.token}
var headers map[string][]string = make(map[string][]string)
headers["Authorization"] = tock
var retry = 0
for retry < 5 {
if err := rest.GetWithHeaders(bloomsky.url, headers); err != nil {
logFatal(err, funcName(), "Problem with call rest, check the URL and the secret ID in the config file or use the mock", bloomsky.url)
retry++
time.Sleep(time.Minute * 5)
} else {
retry = 5
}
}
bloomsky.RefreshFromBody(rest.GetBody())
}
//Refresh from body without call rest
func (bloomsky *bloomsky) RefreshFromBody(body []byte) {
var bloomskyArray []BloomskyStructure
if err := json.Unmarshal(body, &bloomskyArray); err != nil {
logFatal(err, funcName(), "Problem with json to struct", string(body))
}
bloomsky.BloomskyStructure = bloomskyArray[0]
bloomsky.BloomskyStructure.Data.TemperatureC = toFixed(((bloomsky.BloomskyStructure.Data.TemperatureF - 32.00) * 5.00 / 9.00), 2)
bloomsky.BloomskyStructure.Data.Pressurehpa = toFixed((bloomsky.BloomskyStructure.Data.Pressure * 33.8638815), 2)
bloomsky.BloomskyStructure.Storm.WindGustms = toFixed(bloomsky.BloomskyStructure.Storm.WindGust*0.44704, 2)
bloomsky.BloomskyStructure.Storm.WindGustkmh = toFixed(bloomsky.BloomskyStructure.Storm.WindGust*1.60934, 2)
bloomsky.BloomskyStructure.Storm.SustainedWindSpeedms = toFixed(bloomsky.BloomskyStructure.Storm.SustainedWindSpeed*0.44704, 2)
bloomsky.BloomskyStructure.Storm.SustainedWindSpeedkmh = toFixed(bloomsky.BloomskyStructure.Storm.SustainedWindSpeed*1.60934, 2)
bloomsky.BloomskyStructure.Storm.RainDailymm = toFixed(bloomsky.BloomskyStructure.Storm.RainDaily*25.4, 2)
bloomsky.BloomskyStructure.Storm.RainRatemm = toFixed(bloomsky.BloomskyStructure.Storm.RainRate*25.4, 2)
bloomsky.BloomskyStructure.Storm.Rainmm = toFixed(bloomsky.BloomskyStructure.Storm.Rainin*25.4, 2)
bloomsky.BloomskyStructure.LastCall = time.Now().Format("2006-01-02 15:04:05")
logDebug(funcName(), "Refresh From Body", bloomsky.BloomskyStructure.LastCall)
}