Advertisement
tuomasvaltanen

Untitled

Mar 17th, 2023 (edited)
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.68 KB | None | 0 0
  1. // Edistynyt mobiiliohjelmointi, 17.3.2023
  2.  
  3. https://mqttx.app/
  4. https://test.mosquitto.org/
  5.  
  6.  
  7. MQTT X:
  8.  
  9. yhdistetään testibrokeriin:
  10.  
  11. client_id: ei väliä kunhan varmasti uniikki, koska kaksi samaa client id:tä pudottaa vanhemman yhteyden linjoilta
  12. host: test.mosquitto.org
  13. port: 8886
  14. SSL/TLS päälle, SLS Secure ja CA signed server certificate.
  15.  
  16. Esimerkkidataa Ruotsin sääasemasta:
  17. {"d":{"1":{"v":-1.6},"2":{"v":1010.4},"3":{"v":61.4},"4":{"v":-9.1},"6":{"v":103},"7":{"v":0},"8":{"v":0},"9":{"v":302},"10":{"v":1},"11":{"v":12.7}},"ts":"2023-03-17T11:19:24.035Z"}
  18.  
  19. Tehdään uusi fragment mobile_navigationin avulla: WeatherStationFragment.
  20.  
  21. Lisätään WeatherStationFragment päävalikkoon.
  22.  
  23. Otetaan WeatherStationFragmentiin binding layer käyttöön (kopioi pohja esim. DataReadFragmentista)
  24.  
  25. Esim.
  26.  
  27. class WeatherStationFragment : Fragment() {
  28. // change this to match your fragment name
  29. private var _binding: FragmentWeatherStationBinding? = null
  30.  
  31. // This property is only valid between onCreateView and
  32. // onDestroyView.
  33. private val binding get() = _binding!!
  34.  
  35. override fun onCreateView(
  36. inflater: LayoutInflater,
  37. container: ViewGroup?,
  38. savedInstanceState: Bundle?
  39. ): View? {
  40. _binding = FragmentWeatherStationBinding.inflate(inflater, container, false)
  41. val root: View = binding.root
  42.  
  43.  
  44. return root
  45. }
  46.  
  47. override fun onDestroyView() {
  48. super.onDestroyView()
  49. _binding = null
  50. }
  51. }
  52.  
  53. // jotta jsonschema2pojon tuottamat Java-luokat toimii projektissa, tarvitaan seuraava moduuli gradleen:
  54.  
  55. implementation 'javax.annotation:javax.annotation-api:1.3.2'
  56.  
  57. // MQTT:n käyttäminen Fragmentissa
  58.  
  59. import mukaan:
  60. implementation("com.hivemq:hivemq-mqtt-client-shaded:1.3.0")
  61.  
  62. // lisää local.propertiesiin seuraavat muuttujat, ja lisää tarvittavat yhteystiedot (ks. Harjoitus 4, sivu 1)
  63.  
  64. MQTT_BROKER=brokerin_osoite
  65. MQTT_USERNAME=
  66. MQTT_PASSWORD=
  67. MQTT_TOPIC=ruotsin_aseman_topic
  68. MQTT_CLIENT_ID=pelkkä_alkuosa_ilman_omaa_uniikkia_osaa(tehdään koodissa myöhemmin)
  69.  
  70. // WeatherStationFragment, raakadatan lataaminen ja näyttäminen konsolissa:
  71.  
  72. class WeatherStationFragment : Fragment() {
  73. // change this to match your fragment name
  74. private var _binding: FragmentWeatherStationBinding? = null
  75.  
  76. // This property is only valid between onCreateView and
  77. // onDestroyView.
  78. private val binding get() = _binding!!
  79.  
  80. // HiveMQ MQTT ver 3 -client
  81. private lateinit var client: Mqtt3AsyncClient
  82.  
  83. override fun onCreateView(
  84. inflater: LayoutInflater,
  85. container: ViewGroup?,
  86. savedInstanceState: Bundle?
  87. ): View? {
  88. _binding = FragmentWeatherStationBinding.inflate(inflater, container, false)
  89. val root: View = binding.root
  90.  
  91. // version 3, IBM Cloud, weather station
  92. // identifier => lisätään local.propertiesissa olevaan alkuosaan satunnainen teksti
  93. // jotta saadaan uniikki osa myös mukaan (vaadittu IBM Cloudissa)
  94. client = MqttClient.builder()
  95. .useMqttVersion3()
  96. .sslWithDefaultConfig()
  97. .identifier(BuildConfig.MQTT_CLIENT_ID + UUID.randomUUID().toString())
  98. .serverHost(BuildConfig.MQTT_BROKER)
  99. .serverPort(8883)
  100. .buildAsync()
  101.  
  102. client.connectWith()
  103. .simpleAuth()
  104. .username(BuildConfig.MQTT_USERNAME)
  105. .password(BuildConfig.MQTT_PASSWORD.toByteArray())
  106. .applySimpleAuth()
  107. .send()
  108. .whenComplete { connAck: Mqtt3ConnAck?, throwable: Throwable? ->
  109. if (throwable != null) {
  110. Log.d("ADVTECH", "Connection failure.")
  111. } else {
  112. // Setup subscribes or start publishing
  113. subscribeToTopic()
  114. }
  115. }
  116.  
  117. return root
  118. }
  119.  
  120. // apufunktio, jolla tehdään subscription Ruotsin sääasemaan, käytetään
  121. // ainoastaan silloin kun yhteys on saatu luotua onnistuneesti
  122. fun subscribeToTopic()
  123. {
  124. client.subscribeWith()
  125. .topicFilter(BuildConfig.MQTT_TOPIC)
  126. .callback { publish ->
  127.  
  128. // this callback runs everytime your code receives new data payload
  129. var result = String(publish.getPayloadAsBytes())
  130. Log.d("ADVTECH", result)
  131.  
  132. }
  133. .send()
  134. .whenComplete { subAck, throwable ->
  135. if (throwable != null) {
  136. // Handle failure to subscribe
  137. Log.d("ADVTECH", "Subscribe failed.")
  138. } else {
  139. // Handle successful subscription, e.g. logging or incrementing a metric
  140. Log.d("ADVTECH", "Subscribed!")
  141. }
  142. }
  143. }
  144.  
  145. override fun onDestroyView() {
  146. super.onDestroyView()
  147. _binding = null
  148.  
  149. // kannattaa myös katkaista MQTT-yhteys kun fragment suljetaan
  150. client.disconnect()
  151. }
  152. }
  153.  
  154.  
  155. // uusi versio subscribeToTopic -> asetetaan raakadata TextViewiin
  156.  
  157. // apufunktio, jolla tehdään subscription Ruotsin sääasemaan, käytetään
  158. // ainoastaan silloin kun yhteys on saatu luotua onnistuneesti
  159. fun subscribeToTopic()
  160. {
  161. client.subscribeWith()
  162. .topicFilter(BuildConfig.MQTT_TOPIC)
  163. .callback { publish ->
  164.  
  165. // this callback runs everytime your code receives new data payload
  166. var result = String(publish.getPayloadAsBytes())
  167. Log.d("ADVTECH", result)
  168.  
  169. // ajetaan ulkoasuun liittyvät asiat UI-säikeessä
  170. // koska MQTT toimii itsessään taustasäikeessä
  171. // ilman tätä, ohjelma kaatuu
  172. // tämä myös olettaa että ulkoasussa on TextView tällä id:llä
  173. activity?.runOnUiThread(java.lang.Runnable {
  174. binding.textViewWeatherData.text = result
  175. })
  176.  
  177. }
  178. .send()
  179. .whenComplete { subAck, throwable ->
  180. if (throwable != null) {
  181. // Handle failure to subscribe
  182. Log.d("ADVTECH", "Subscribe failed.")
  183. } else {
  184. // Handle successful subscription, e.g. logging or incrementing a metric
  185. Log.d("ADVTECH", "Subscribed!")
  186. }
  187. }
  188. }
  189.  
  190.  
  191. // uusi versio subscribeToTopic, GSON + try/catch:
  192.  
  193. // apufunktio, jolla tehdään subscription Ruotsin sääasemaan, käytetään
  194. // ainoastaan silloin kun yhteys on saatu luotua onnistuneesti
  195. fun subscribeToTopic()
  196. {
  197. val gson = GsonBuilder().setPrettyPrinting().create()
  198.  
  199. client.subscribeWith()
  200. .topicFilter(BuildConfig.MQTT_TOPIC)
  201. .callback { publish ->
  202. // this callback runs everytime your code receives new data payload
  203. var result = String(publish.getPayloadAsBytes())
  204. Log.d("ADVTECH", result)
  205.  
  206. // try-catchin avulla voimme huolehtia ettei koodi tilttaa
  207. // kun sääasema lähettää diagnostiikka-payloadin (joka ei sisällä säädataa)
  208. try {
  209. var item : WeatherStation = gson.fromJson(result, WeatherStation::class.java)
  210.  
  211. // haetaan lämpötila WeatherStation-objektin kautta
  212. // haetaan myös ilmanpaine
  213. var temperature = item.d.get1().v.toString()
  214. var pressure = item.d.get2().v.toString()
  215.  
  216. // rakennetaan simppeli teksti ulkoasua varten
  217. var output = "Temp: ${temperature} C\nPressure:${pressure}"
  218.  
  219. // ajetaan ulkoasuun liittyvät asiat UI-säikeessä
  220. // koska MQTT toimii itsessään taustasäikeessä
  221. // ilman tätä, ohjelma kaatuu
  222. activity?.runOnUiThread(java.lang.Runnable {
  223. binding.textViewWeatherData.text = output
  224. })
  225. }
  226. catch(e: Exception) {
  227. Log.d("ADVTECH", "Skipped diagnostics payload.")
  228. }
  229.  
  230.  
  231. }
  232. .send()
  233. .whenComplete { subAck, throwable ->
  234. if (throwable != null) {
  235. // Handle failure to subscribe
  236. Log.d("ADVTECH", "Subscribe failed.")
  237. } else {
  238. // Handle successful subscription, e.g. logging or incrementing a metric
  239. Log.d("ADVTECH", "Subscribed!")
  240. }
  241. }
  242. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement