Guest User

Untitled

a guest
Mar 22nd, 2017
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.36 KB | None | 0 0
  1. # Version: 1
  2. # Author: Joachim Olsson
  3. # Date: 2016-10-05
  4. #
  5. # This file detects hardware pulses from energy meter and logs them
  6. # The default input pin is GPIO24 on raspberry pi
  7. # Each tick on this pin is worth 10 Wh
  8. # This is stored in memory, and written to file by default once every minute
  9.  
  10. import RPi.GPIO as GPIO
  11. import datetime
  12. import time
  13. import os
  14. import sys
  15. import linecache
  16. import requests
  17. import json
  18. import threading
  19. from random import randint, uniform
  20. import re
  21.  
  22. def RunScript(script):
  23. os.system('sudo python ' + script)
  24.  
  25. def LogException(Info):
  26. f = None
  27. try:
  28. LoggingLock.acquire()
  29. locked = True
  30. f = open(os.getcwd() + LogFile, "a+")
  31. dateTime = datetime.datetime.utcnow()
  32. data = f.read()
  33. f.seek(0)
  34. f.truncate()
  35. jsonData = json.loads(data)
  36. jsonData['ExceptionEntries'].append({'Time': dateTime.isoformat(), 'Exception': Info})
  37. f.write(json.dumps(jsonData))
  38. except ValueError as ex:
  39. #Error in data, input valid sequence in file
  40. print "LogException: "
  41. print ex
  42. print 'Decoding JSON failed! Document:'
  43. print data
  44. jsonData = {
  45. 'LogEntries': [],
  46. 'DeviceEntries': [],
  47. 'ExceptionEntries': [{'Time': dateTime.isoformat(), 'ExceptionInfo': Info}]
  48. }
  49.  
  50. f.write(json.dumps(jsonData))
  51. print '\nJSON Data Restored!'
  52. locked = False
  53. f.close()
  54. LoggingLock.release()
  55. LogAction('TRUNCATING DATA: (Log Exception ValueError)')
  56. except Exception as ex:
  57. f.close()
  58. locked = False
  59. LoggingLock.release()
  60. LogExceptionInfo()
  61. finally:
  62. if(f and not f.closed):
  63. f.close()
  64. if(locked):
  65. LoggingLock.release()
  66.  
  67. def LogExceptionInfo():
  68. try:
  69. exc_type, exc_obj, tb = sys.exc_info()
  70. f = tb.tb_frame
  71. lineno = tb.tb_lineno
  72. filename = f.f_code.co_filename
  73. linecache.checkcache(filename)
  74. line = linecache.getline(filename, lineno, f.f_globals)
  75. dateTime = datetime.datetime.utcnow()
  76. text = '[{}] EXCEPTION OCCURRED IN ({}, LINE {} "{}"): {}'.format(dateTime, filename, lineno, line.strip(), exc_obj)
  77. print text
  78. LogException(text)
  79. except ValueError as ex:
  80. print ex
  81. LogExceptionInfo()
  82. except Exception as ex:
  83. LogExceptionInfo()
  84.  
  85. def GetAuthorizationToken():
  86. try:
  87. AuthorizationLock.acquire()
  88. locked = True
  89. global AuthorizationType, AuthorizationCredentials, AuthorizationExpires, Authorized
  90. data = {
  91. 'username': LoginAccountUsername,
  92. 'password': LoginAccountPassword,
  93. 'grant_type': 'password'
  94. }
  95. response = requests.post(BaseAuth, data = data)
  96. data = response.json()
  97.  
  98. if(response.status_code == 200):
  99. AuthorizationExpires = datetime.datetime.utcnow() + datetime.timedelta(seconds=data['expires_in']) - datetime.timedelta(seconds=1)
  100. AuthorizationCredentials = data['access_token']
  101. AuthorizationType = "Bearer "
  102. Authorized = True
  103. print "Authorization Expires at: " + str(AuthorizationExpires)
  104. print "Authorization Type: " + str(AuthorizationType)
  105. print "Authorization Credentials: " + str(AuthorizationCredentials)
  106. LogAction("LOGIN SUCCESS")
  107. else:
  108. Authorized = False
  109. LogAction("LOGIN FAIL")
  110. except:
  111. LogExceptionInfo()
  112. finally:
  113. if(locked):
  114. AuthorizationLock.release()
  115.  
  116. def GetUpdates():
  117. f = None
  118. success = False
  119. try:
  120. AuthorizationLock.acquire()
  121. headers = { "Authorization" : AuthorizationType + AuthorizationCredentials, "Accept": "text/*", "Accept-Encoding": "gzip;q=1.0, deflate;q=0.8, *;q=0" }
  122. response = requests.get(BaseAPI + "/Logging/GetUpdater", headers = headers)
  123. disposition = response.headers['content-disposition']
  124. filename = re.findall("filename=(.+)", disposition)[0]
  125.  
  126. f = open(os.getcwd() + "/" + filename, "a+")
  127. f.seek(0)
  128. f.truncate()
  129. f.write(unicode(response.content, "UTF-8"))
  130. LogAction("DOWNLOAD UPDATER: " + filename)
  131. print "Downloaded Updater: " + filename
  132. success = True
  133. except:
  134. LogExceptionInfo()
  135. finally:
  136. AuthorizationLock.release()
  137. if(f and not f.closed):
  138. f.close()
  139.  
  140. if(success):
  141. try:
  142. RunScript(os.getcwd() + "/" + filename)
  143. LogAction("OS EXIT (UPDATING...)")
  144. os._exit(1)
  145. except:
  146. LogExceptionInfo()
  147.  
  148. def GetConfig():
  149. global Authorized, HardwareLogInterval, PostInterval
  150. LatestBuild = CurrentBuild
  151. try:
  152. AuthorizationLock.acquire()
  153. locked = True
  154. authorized = Authorized
  155. except:
  156. LogExceptionInfo()
  157. finally:
  158. if(locked):
  159. AuthorizationLock.release()
  160.  
  161. try:
  162. if(not authorized):
  163. GetAuthorizationToken()
  164. except:
  165. LogExceptionInfo()
  166.  
  167. try:
  168. AuthorizationLock.acquire()
  169. locked = True
  170. headers = { "Authorization" : AuthorizationType + AuthorizationCredentials, "Accept": "application/json", "Accept-Encoding": "gzip;q=1.0, deflate;q=0.8, *;q=0" }
  171. response = requests.get(BaseAPI + "/Logging/GetConfig", headers = headers)
  172. data = response.json()
  173. if(response.status_code == 200):
  174. try:
  175. ConfigLock.acquire()
  176. Status = data['Status']
  177. HardwareLogInterval = datetime.timedelta(seconds=data['LogInterval'])
  178. PostInterval = datetime.timedelta(seconds=data['PostInterval'])
  179. NextLogTime = datetime.datetime.utcnow() + HardwareLogInterval
  180. NextPostTime = datetime.datetime.utcnow() + PostInterval
  181. LatestBuild = data['LatestBuild']
  182. '''print "Retrieved config"
  183. print "Status: " + str(Status)
  184. print "LogInterval: " + str(HardwareLogInterval)
  185. print "PostInterval: " + str(PostInterval)'''
  186. LogAction("GET CONFIG")
  187. except:
  188. LogExceptionInfo()
  189. finally:
  190. ConfigLock.release()
  191. else:
  192. authorized = False
  193. LogAction("GET CONFIG FAIL")
  194. except:
  195. LogExceptionInfo()
  196. finally:
  197. if(locked):
  198. AuthorizationLock.release()
  199.  
  200. try:
  201. if(not authorized):
  202. GetAuthorizationToken()
  203. except:
  204. LogExceptionInfo()
  205.  
  206. if(LatestBuild != CurrentBuild):
  207. GetUpdates()
  208.  
  209. def GetCPUSerial():
  210. cpuSerial = '0000000000000000'
  211. try:
  212. f = open('/proc/cpuinfo','r') #RPi Serial location
  213. for line in f:
  214. if line[0:6]=='Serial':
  215. cpuSerial = line[10:26]
  216. return int(str(cpuSerial), 16)
  217. except Exception as ex:
  218. LogExceptionInfo()
  219. finally:
  220. f.close()
  221.  
  222. def StartHardwareLogger():
  223. try:
  224. print "StartHardwareLogger"
  225. GPIO.setwarnings(False)
  226. GPIO.setmode(GPIO.BCM)
  227. GPIO.setup(HardwarePin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
  228. GPIO.add_event_detect(HardwarePin, GPIO.RISING, callback=HardwareLoggerCallback, bouncetime=BounceIntervalMs)
  229. except:
  230. LogExceptionInfo()
  231.  
  232. def HardwareLoggerCallback(ch):
  233. try:
  234. global CurrentEnergyLevel,CountEnergyTicks,DateTime,NextLogTime
  235. CurrentEnergyLevel += 10
  236. CountEnergyTicks += 1
  237. DateTime = datetime.datetime.utcnow()
  238. if(DateTime >= NextLogTime and CurrentEnergyLevel > 0):
  239. NextLogTime = DateTime + HardwareLogInterval
  240. LogEntry(CurrentEnergyLevel)
  241. CurrentEnergyLevel = 0
  242. '''if (CountEnergyTicks >= 3):
  243. print "HardwareLoggerCallback 3"
  244. GPIO.remove_event_detect(HardwarePin)
  245. GPIO.cleanup()
  246. StartHardwareLogger()'''
  247. except:
  248. #GPIO.cleanup()
  249. LogExceptionInfo()
  250. #StartHardwareLogger()
  251.  
  252. def LogEntry(EnergyLevel):
  253. f = None
  254. try:
  255. LoggingLock.acquire()
  256. locked = True
  257. f = open(os.getcwd() + LogFile, "a+")
  258. dateTime = datetime.datetime.utcnow()
  259. data = f.read()
  260. f.seek(0)
  261. f.truncate()
  262. jsonData = json.loads(data)
  263. jsonData['LogEntries'].append({
  264. 'Time': dateTime.isoformat(),
  265. 'EnergyAmount': EnergyLevel,
  266. })
  267. f.write(json.dumps(jsonData))
  268. except ValueError as ex:
  269. #Error in data, input valid sequence in file
  270. print 'Decoding JSON failed! Document:'
  271. print data
  272. jsonData = {
  273. 'LogEntries': [{
  274. 'Time': dateTime.isoformat(),
  275. 'EnergyAmount': EnergyLevel
  276. }],
  277. 'DeviceEntries': [],
  278. 'ExceptionEntries': []
  279. }
  280. f.write(json.dumps(jsonData))
  281. f.close()
  282. locked = False
  283. LoggingLock.release()
  284. print 'JSON Data Restored!'
  285. LogAction("TRUNCATING DATA: (Log Entry ValueError)")
  286. except Exception as ex:
  287. if(f and not f.closed):
  288. f.close()
  289. locked = False
  290. LoggingLock.release()
  291. LogExceptionInfo()
  292. finally:
  293. if(f and not f.closed):
  294. f.close()
  295. if(locked):
  296. LoggingLock.release()
  297.  
  298. def LogAction(Info):
  299. f = None
  300. try:
  301. LoggingLock.acquire()
  302. locked = True
  303. f = open(os.getcwd() + LogFile, "a+")
  304. dateTime = datetime.datetime.utcnow()
  305. data = f.read()
  306. f.seek(0)
  307. f.truncate()
  308. jsonData = json.loads(data)
  309. jsonData['DeviceEntries'].append({'Time': dateTime.isoformat(), 'Action': Info})
  310. f.write(json.dumps(jsonData))
  311. except ValueError as ex:
  312. #Error in data, input valid sequence in file
  313. print 'Decoding JSON failed! Document:'
  314. print data
  315. jsonData = {
  316. 'LogEntries': [],
  317. 'DeviceEntries': [{'Time': dateTime.isoformat(), 'Action': Info}],
  318. 'ExceptionEntries': []
  319. }
  320. f.write(json.dumps(jsonData))
  321. locked = False
  322. f.close()
  323. LoggingLock.release()
  324. print 'JSON Data Restored!'
  325. LogAction("TRUNCATING DATA: (Log Action ValueError)")
  326. except Exception as ex:
  327. if(f and not f.closed):
  328. f.close()
  329. locked = False
  330. LoggingLock.release()
  331. LogExceptionInfo()
  332. finally:
  333. if(f and not f.closed):
  334. f.close()
  335. if(locked):
  336. LoggingLock.release()
  337.  
  338. def CheckAuthorize():
  339. global Authorized
  340. if(datetime.datetime.utcnow() >= AuthorizationExpires):
  341. AuthorizationLock.acquire()
  342. print "Authorization Invalid"
  343. Authorized = False
  344. AuthorizationLock.release()
  345. while(True):
  346. print "Re-authorizing"
  347. GetAuthorizationToken()
  348. if(Authorized):
  349. break
  350. else:
  351. time.sleep(30)
  352.  
  353. def CheckPostLog():
  354. global NextPostTime, PostInterval, HardwareLogInterval, NextLogTime, Status
  355. f = None
  356. LatestBuild = CurrentBuild
  357. if(datetime.datetime.utcnow() >= NextPostTime):
  358. try:
  359. print "Posting log..."
  360. LoggingLock.acquire()
  361. locked = True
  362. NextPostTime = datetime.datetime.utcnow() + PostInterval
  363. f = open(os.getcwd() + LogFile, "a+")
  364. jsonData = json.loads(f.read())
  365. jsonData['Time'] = datetime.datetime.utcnow().isoformat()
  366. headers = { "Authorization" : AuthorizationType + AuthorizationCredentials, "Accept": "application/json", "Content-Type": "application/json" }
  367. response = requests.post(BaseAPI + "/Logging/Log", headers = headers, json=jsonData)
  368. data = response.json()
  369. if(response.status_code == 200):
  370. f.seek(0)
  371. f.truncate()
  372. jsonData = {
  373. 'LogEntries': [],
  374. 'DeviceEntries': [],
  375. 'ExceptionEntries': []
  376. }
  377. f.write(json.dumps(jsonData))
  378. try:
  379. ConfigLock.acquire()
  380. Status = data['Status']
  381. HardwareLogInterval = datetime.timedelta(seconds=data['LogInterval'])
  382. PostInterval = datetime.timedelta(seconds=data['PostInterval'])
  383. NextLogTime = datetime.datetime.utcnow() + HardwareLogInterval
  384. NextPostTime = datetime.datetime.utcnow() + PostInterval
  385. LatestBuild = data['LatestBuild']
  386. except Exception as ex:
  387. LogAction("SAVE POST LOG CONFIG FAILURE: { DATA: { " + data + " }, EXCEPTION: {" + ex + " } ")
  388. finally:
  389. ConfigLock.release()
  390. else:
  391. LogAction("POST LOG FAILURE: " + str(data))
  392. print "Error Sending Log: "
  393. print data
  394. except ValueError as ex:
  395. if(f and not f.closed):
  396. f.seek(0)
  397. f.truncate()
  398. jsonData = {
  399. 'LogEntries': [],
  400. 'DeviceEntries': [],
  401. 'ExceptionEntries': []
  402. }
  403. f.write(json.dumps(jsonData))
  404. locked = False
  405. LoggingLock.release()
  406. LogAction("TRUNCATING DATA: (POST LOG ValueError)")
  407. except:
  408. if(f and not f.closed):
  409. f.close()
  410. locked = False
  411. LoggingLock.release()
  412. LogExceptionInfo()
  413. finally:
  414. if(f and not f.closed):
  415. f.close()
  416. if(locked):
  417. LoggingLock.release()
  418.  
  419. try:
  420. if(LatestBuild != CurrentBuild):
  421. GetUpdates()
  422. except:
  423. LogExceptionInfo()
  424.  
  425.  
  426.  
  427.  
  428. ########-----Global Variables-----########
  429. ConfigLock = threading.Lock()
  430.  
  431. Status = 0
  432. PostInterval = datetime.timedelta(seconds=3)
  433. HardwareLogInterval = datetime.timedelta(seconds=5) #How often to log to file
  434. DateTime = datetime.datetime.utcnow()
  435. NextLogTime = DateTime + HardwareLogInterval
  436. NextPostTime = DateTime + PostInterval
  437. BounceIntervalMs = 50 #Note, anything logged in this interval won't be counted
  438. HardwarePin = 24 #GPIO24
  439.  
  440.  
  441. AuthorizationLock = threading.Lock()
  442.  
  443. BaseAPI = "http://192.168.1.16:8080/API/"
  444. BaseAuth = "http://192.168.1.16:8080/oauth/token"
  445. AuthorizationType = ""
  446. AuthorizationCredentials = ""
  447. AuthorizationExpires = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
  448. Authorized = False
  449. LoginAccountUsername = "Device@AndrewPeters"
  450. LoginAccountPassword = "p4ssw0rd"
  451.  
  452.  
  453. LoggingLock = threading.Lock()
  454.  
  455. CurrentEnergyLevel = 0
  456. CountEnergyTicks = 0
  457. #CPUSerial = GetCPUSerial()
  458. LogFile = "/Log.json"
  459. UpdaterFile = "/Updater.py"
  460. CurrentBuild = 2
  461.  
  462. ########-----Main Program-----########
  463. print "\n==================="
  464. print "PowerCoins Logger - Running"
  465. print "===================\n"
  466.  
  467. while True:
  468. try:
  469. LogAction("BOOT")
  470. #StartHardwareLogger()
  471. CheckAuthorize()
  472. GetConfig()
  473. while True:
  474. print "Looping"
  475. approachingRandom = 50
  476. lastRandom = 50
  477. if(randint(0,15) > 14):
  478. if(lastRandom == approachingRandom):
  479. approachingRandom = randint(30, 120)
  480. lastRandom = round((approachingRandom - lastRandom) * uniform(0, 1), 0)
  481. LogEntry(lastRandom)
  482.  
  483. CheckAuthorize()
  484. CheckPostLog()
  485. time.sleep(3) #To give time to OS to relax
  486.  
  487. except Exception as e:
  488. print e
  489. LogAction("EXIT(AUTORESTART)")
  490. GPIO.cleanup()
Advertisement
Add Comment
Please, Sign In to add comment