weather.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. var cardInfo = {
  2. id: -1,
  3. responseTopic: '/weatherCard_' + getEpochMillis(),
  4. // bgColor: 0xc44569,
  5. bgColor: 0x0,
  6. params: {
  7. location: 'Toronto,CA',
  8. tempUnit: 'fahrenheit',
  9. distanceUnit: 'imperial',
  10. prevCalendarDay: -1,
  11. prevUpdate: 0,
  12. updateInterval: 15*60*1000 // 15 min
  13. },
  14. enabled: true
  15. }
  16. // definitions for the program
  17. var elementId = {
  18. weatherUnitIndicator: 0,
  19. weatherTemperature: 1,
  20. weatherMainImage: 2,
  21. date: 3,
  22. weatherParameterIcon: 4,
  23. weatherParameterValue: 5,
  24. weatherParameterUnits: 6,
  25. separator: 7,
  26. cover: 8
  27. }
  28. var weatherImg = {
  29. degree: "degree",
  30. degreeC: "degC",
  31. degreeF: "degF",
  32. oboo: "oboo",
  33. '01d': 'sunny',
  34. '01n': 'night-clear',
  35. '02d': 'cloudy',
  36. '02n': 'night',
  37. '03d': 'cloudy-1',
  38. '03n': 'cloudy-1',
  39. '04d': 'cloudy-1',
  40. '04n': 'cloudy-1',
  41. '09d': 'rain',
  42. '09n': 'rain',
  43. '10d': 'rainbow-1',
  44. '10n': 'night-1',
  45. '11d': 'thunderstorm',
  46. '11n': 'thunderstorm',
  47. '13d': 'snowy',
  48. '13n': 'snowy',
  49. '50d': 'fog-1',
  50. '50n': 'fog',
  51. 'wind-speed': 'wind-sign',
  52. 'humidity': 'humidity',
  53. 'pressure': 'pressure',
  54. 'temp-hi-lo': 'temp-hi-lo',
  55. separator: "line",
  56. }
  57. function getFormattedDate () {
  58. var weekdays = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
  59. var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "June",
  60. "July", "Aug", "Sept", "Oct", "Nov", "Dec"
  61. ]
  62. var date = new Date()
  63. return {
  64. weekday: weekdays[date.getDay()],
  65. month: monthNames[date.getMonth()],
  66. day: date.getDate()
  67. }
  68. }
  69. function createCard () {
  70. var dateObj = getFormattedDate()
  71. var cardObj = generateNewCardObj(cardInfo.bgColor, cardInfo.responseTopic)
  72. cardObj.elements.push(generateImageElement(
  73. elementId.weatherUnitIndicator,
  74. generateImgPath(imgRootPath, weatherImg['degree']),
  75. 200, 50) )
  76. cardObj.elements.push(generateTextElement(
  77. elementId.weatherTemperature,
  78. '--',
  79. 82,
  80. -40, 40, 'right') )
  81. // main weather image
  82. cardObj.elements.push(generateImageElement(
  83. elementId.weatherMainImage,
  84. generateImgPath(imgRootPath, weatherImg['oboo']),
  85. // generateImgPath(imgRootPath, weatherImg['sunny']),
  86. 10, 5)
  87. )
  88. // date
  89. cardObj.elements.push(generateTextElement(
  90. elementId.date,
  91. dateObj.weekday + ', ' + dateObj.month + ' ' + dateObj.day,
  92. 23,
  93. 0, 160, 'center')
  94. )
  95. cardObj.elements.push(generateImageElement(
  96. elementId.weatherParameterIcon,
  97. generateImgPath(imgRootPath, weatherImg['wind-speed']),
  98. 30, 205)
  99. )
  100. cardObj.elements.push(generateTextElement(
  101. elementId.weatherParameterValue,
  102. '--',
  103. 50,
  104. -64, 209, 'right')
  105. )
  106. cardObj.elements.push(generateTextElement(
  107. elementId.weatherParameterUnits,
  108. 'km/h',
  109. 23,
  110. 180, 233, 'left')
  111. )
  112. // line separator
  113. cardObj.elements.push(generateImageElement(
  114. elementId.separator,
  115. generateImgPath(imgRootPath, weatherImg['separator']),
  116. 21, 190)
  117. )
  118. // init the card
  119. initCard(JSON.stringify(cardObj), true)
  120. }
  121. var cycleCounter = 100
  122. function cycleInfo () {
  123. cycleCounter += 1
  124. if (cycleCounter >= 100) {
  125. cycleCounter = 0
  126. return true
  127. } else {
  128. cycleCounter += 1
  129. return false
  130. }
  131. }
  132. var weather
  133. function updateWeather () {
  134. var result = getYahooWeather(cardInfo.params.location, cardInfo.params.tempUnit, cardInfo.params.distanceUnit)
  135. if (result !== null) {
  136. weather = result
  137. updateDisplay(true)
  138. return true
  139. } else {
  140. return false
  141. }
  142. }
  143. var secIndex = 0
  144. function updateDisplay (forceUpdate) {
  145. var updateObj = generateUpdateCardObj(cardInfo.id)
  146. var update = forceUpdate?true:false
  147. /* Date */
  148. var dateObj = getFormattedDate()
  149. // only update if the calendar day has changed
  150. if (cardInfo.params.prevCalendarDay !== dateObj.day) {
  151. updateObj.elements.push(generateElementUpdate(
  152. elementId.date,
  153. dateObj.weekday + ', ' + dateObj.month + ' ' + dateObj.day)
  154. )
  155. // update the prev day variable
  156. cardInfo.params.prevCalendarDay = dateObj.day
  157. update = true
  158. }
  159. /* Weather */
  160. if (weather !== null) {
  161. // update Main info
  162. updateObj.elements.push(generateElementUpdate(
  163. elementId.weatherTemperature,
  164. weather.temperature)
  165. )
  166. updateObj.elements.push(generateElementUpdate(
  167. elementId.weatherMainImage,
  168. generateImgPath(imgRootPath, weatherImg[weather.condition])
  169. )
  170. )
  171. updateObj.elements.push(generateElementUpdate(
  172. elementId.weatherUnitIndicator,
  173. generateImgPath(imgRootPath, weatherImg[cardInfo.params.tempUnit === 'fahrenheit'?'degreeF':'degreeC'])
  174. )
  175. )
  176. // update Secondary info
  177. if (cycleInfo()) {
  178. secIndex += 1
  179. secIndex %= weather.secondary.length
  180. update = true
  181. }
  182. var secInfo = weather.secondary[secIndex]
  183. updateObj.elements.push(generateElementUpdate(
  184. elementId.weatherParameterIcon,
  185. generateImgPath(imgRootPath, weatherImg[secInfo.type]))
  186. )
  187. updateObj.elements.push(generateElementUpdate(
  188. elementId.weatherParameterValue,
  189. secInfo.value)
  190. )
  191. updateObj.elements.push(generateElementUpdate(
  192. elementId.weatherParameterUnits,
  193. secInfo.unit)
  194. )
  195. }
  196. if (update) {
  197. updateCard(JSON.stringify(updateObj))
  198. }
  199. }
  200. function readConfig() {
  201. readFile('/etc/config.json', '', function (err, data) {
  202. if (!err) {
  203. var config;
  204. try {
  205. config = JSON.parse(data);
  206. } catch(e) {
  207. print(e); // error in the above string!
  208. return null;
  209. }
  210. // apply the settings from the config file
  211. cardIdentifier = 0; // TODO: this is temporary
  212. cardInfo.params.location = config.cards['0'].location || cardInfo.params.location;
  213. cardInfo.params.tempUnit = config.cards['0'].tempUnit || cardInfo.params.tempUnit;
  214. cardInfo.params.distanceUnit = config.cards['0'].distanceUnit || cardInfo.params.distanceUnit;
  215. print(config.cards['0'].distanceUnit);
  216. if(config.cards['0'] && config.cards['0'].enabled !== undefined){
  217. cardInfo.enabled = config.cards['0'].enabled && cardInfo.enabled;
  218. }
  219. }
  220. print("card is enabled: " + cardInfo.enabled);
  221. print('configuration: location = ' + cardInfo.params.location + '; temperature unit = ' + cardInfo.params.tempUnit + '; distance unit = ' + cardInfo.params.distanceUnit);
  222. });
  223. }
  224. function setup() {
  225. readConfig();
  226. if(cardInfo.enabled == true){
  227. connect('localhost', 1883, null, function () {
  228. subscribe('/cardResponse', function () {
  229. createCard();
  230. });
  231. subscribe('/config/update');
  232. // subscribe('/button');
  233. // subscribe('/gesture');
  234. },
  235. null,
  236. '/card',
  237. JSON.stringify({
  238. cmd: 'remove_card',
  239. cardName: cardInfo.responseTopic
  240. })
  241. );
  242. }
  243. }
  244. function loop() {
  245. // return if card not initialized
  246. if (cardInfo.id < 0) return
  247. // exit program if card is invalid
  248. if (cardInfo.invalid === true) return -1
  249. // update weather in every {{updateInterval}}
  250. if ((new Date - cardInfo.params.prevUpdate) > cardInfo.params.updateInterval) {
  251. if ( updateWeather() ){
  252. // reset time stamp if successful
  253. cardInfo.params.prevUpdate = new Date
  254. } else {
  255. // check back in 1 minute
  256. cardInfo.params.prevUpdate = new Date - (cardInfo.params.updateInterval - 1 * 60 * 1000)
  257. }
  258. }
  259. // update display every loop
  260. updateDisplay()
  261. }
  262. function onInput(e) {
  263. if (typeof e.source !== 'undefined' && typeof e.payload !== 'undefined' ) {
  264. print('input! input source: ' + e.source + ', value: ' + e.payload)
  265. }
  266. }
  267. function onMessage(e) {
  268. if (typeof e.topic !== 'undefined' && typeof e.payload !== 'undefined' ) {
  269. print('message! topic: ' + e.topic + ', value: ' + e.payload)
  270. switch (e.topic) {
  271. case '/cardResponse':
  272. cardInfo = handleCardResponseMessage(cardInfo, e.payload)
  273. break
  274. case '/config/update':
  275. readConfig()
  276. cardInfo.params.prevUpdate = 0 // force an update
  277. break
  278. default:
  279. break
  280. }
  281. }
  282. }