fridge-alarm.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #!/usr/local/bin/python2
  2. #
  3. # Copyright (c) 2017-2018 Joe Clarke <jclarke@cisco.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions
  8. # are met:
  9. # 1. Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. # notice, this list of conditions and the following disclaimer in the
  13. # documentation and/or other materials provided with the distribution.
  14. #
  15. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. # SUCH DAMAGE.
  26. import sys
  27. import sparker
  28. import re
  29. import requests
  30. import json
  31. import logging
  32. import traceback
  33. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  34. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  35. import CLEUCreds
  36. TEAM_NAME = 'CL18-Infra_team'
  37. BEER_ROOM_NAME = 'Beer Alarms'
  38. OPI_ROOM_NAME = 'CL18 - Operational Insights Demo'
  39. LOGIN_URL_1 = 'https://am-api.cmxcisco.com/api/tm/v1/account/local/login'
  40. LOGIN_URL_2 = 'https://am-api.cmxcisco.com/api/tm/v1/account/registered/apps/31'
  41. LOGIN_URL_3 = 'https://opinsights.cisco.com/api/am/v1/auth/user/current/user'
  42. CMX_URL = 'http://10.100.253.13:8002/api/v0.1/cmx'
  43. SENSOR_URL = 'https://opinsights.cisco.com/api/am/v1/entities/tags/30'
  44. HEADERS = {
  45. 'Authorization': 'Basic {}'.format(CLEUCreds.OPINSIGHT_BASIC)
  46. }
  47. OUR_TENANT = 31
  48. if __name__ == '__main__':
  49. spark = sparker.Sparker(True)
  50. print('Content-type: application/json\r\n\r\n')
  51. output = sys.stdin.read()
  52. j = json.loads(output)
  53. logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s : %(message)s',
  54. filename='/var/log/fridge-alarm.log', level=logging.DEBUG)
  55. logging.debug(json.dumps(j, indent=4))
  56. message = j['message']
  57. us = 'Anonymous'
  58. noc_fridge = 'NOC Fridge'
  59. if 'name' in j['assets'][0]:
  60. us = j['assets'][0]['name']
  61. if us == noc_fridge:
  62. try:
  63. response = requests.request(
  64. 'POST', LOGIN_URL_1, headers=HEADERS, verify=False)
  65. response.raise_for_status()
  66. except Exception as e:
  67. logging.error('Failed to login to {}: {}'.format(LOGIN_URL_1, e))
  68. print(json.dumps({'result': 'fail'}))
  69. sys.exit(1)
  70. login1 = response.json()
  71. token1 = None
  72. for account in login1['accountDetails']:
  73. if account['tenantId'] == OUR_TENANT:
  74. token1 = account['token']
  75. break
  76. if token1 is None:
  77. logging.error('Failed to get token from {}'.format(response.text))
  78. print(json.dumps({'result': 'fail'}))
  79. sys.exit(1)
  80. headers = {
  81. 'Authorization': 'JWT {}'.format(token1)
  82. }
  83. try:
  84. response = requests.request(
  85. 'GET', LOGIN_URL_2, headers=headers, verify=False)
  86. response.raise_for_status()
  87. except Exception as e:
  88. logging.error('Failed to login to {}: {}'.format(LOGIN_URL_2, e))
  89. print(json.dumps({'result': 'fail'}))
  90. sys.exit(1)
  91. try:
  92. response = requests.request(
  93. 'GET', LOGIN_URL_3, headers=headers, verify=False)
  94. response.raise_for_status()
  95. except Exception as e:
  96. logging.error('Failed to login to {}: {}'.format(LOGIN_URL_3, e))
  97. print(json.dumps({'result': 'fail'}))
  98. sys.exit(1)
  99. login3 = response.json()
  100. token2 = login3['token']
  101. headers = {
  102. 'Authorization': 'JWT {}'.format(token2)
  103. }
  104. try:
  105. response = requests.request(
  106. 'GET', SENSOR_URL, headers=headers, verify=False)
  107. response.raise_for_status()
  108. except Exception as e:
  109. logging.error(
  110. 'Failed to get sensor info from {}: {}'.format(SENSOR_URL, e))
  111. print(json.dumps({'result': 'fail'}))
  112. sys.exit(1)
  113. sensor_data = response.json()
  114. logging.debug('Read {}'.format(json.dumps(sensor_data, indent=4)))
  115. temperature = None
  116. for datum in sensor_data['data']:
  117. if datum['data']['units'] == 'Degrees Celsius':
  118. temperature = datum['data']['measurement']
  119. break
  120. msg = 'Hey, all! Your friendly **{}** sent a message: _{}_.'
  121. if temperature is not None:
  122. msg += ' Additionally, the temperature of your beer is now **{}** &#176;C'
  123. spark.post_to_spark(TEAM_NAME, BEER_ROOM_NAME,
  124. msg.format(us, message, temperature))
  125. else:
  126. mac_address = j['assets'][0]['macAddresses'][0]
  127. url = CMX_URL
  128. headers = {
  129. 'Accept': 'image/jpeg, application/json'
  130. }
  131. loc_image = None
  132. response = None
  133. try:
  134. response = requests.request(
  135. 'GET', url, headers=headers, params={'tag': mac_address.lower(), 'marker': 'green', 'size': 1440}, stream=True)
  136. response.raise_for_status()
  137. except Exception:
  138. logging.error('Encountered error getting data from cmx: {}'.format(
  139. traceback.format_exc()))
  140. if response is not None and response.headers.get('content-type') == 'application/json':
  141. loc_image = None
  142. elif response is not None:
  143. loc_image = response.raw.data
  144. msg = '{} {}'.format(message, us)
  145. spark.post_to_spark(TEAM_NAME, OPI_ROOM_NAME, msg)
  146. if loc_image is not None:
  147. spark.post_to_spark_with_attach(TEAM_NAME, OPI_ROOM_NAME, '{}\'s location from CMX'.format(
  148. us), loc_image, '{}_location.jpg'.format(us), 'image/jpeg')
  149. print(json.dumps({'result': 'success'}))