rules_test.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package worker
  2. import (
  3. "encoding/json"
  4. "reflect"
  5. "testing"
  6. )
  7. type TestRuleStruct struct {
  8. RuleName string
  9. RuleSrc string
  10. JsonSrc string
  11. JsonExp string
  12. }
  13. var TestingRules = []TestRuleStruct{
  14. TestRuleStruct{
  15. RuleName: "tasmotaTemp",
  16. RuleSrc: `[
  17. {"operation": "shift",
  18. "spec": {
  19. "Temperature": "DS18B20.Temperature",
  20. "TempUnit": "TempUnit",
  21. "Time": "Time"
  22. }
  23. }
  24. ]`,
  25. JsonSrc: `{"Time":"2020-04-27T08:47:07","DS18B20":{"Id":"0114556E95AA","Temperature":26.9},"TempUnit":"C"}`,
  26. JsonExp: `{"Time":"2020-04-27T08:47:07", "Temperature":26.9,"TempUnit":"C"}`,
  27. },
  28. TestRuleStruct{
  29. RuleName: "hmBWMMotion",
  30. RuleSrc: `[
  31. {"operation": "shift",
  32. "spec": {
  33. "Device": "hm.channelName",
  34. "Motion": "hm.valueStable",
  35. "Time": "ts"
  36. }
  37. }
  38. ]`,
  39. JsonSrc: `{"val":false,"ts":1587971766000,"lc":1587971766000,"hm":{"ccu":"localhost","iface":"BidCos-RF","device":"LTK0028082","deviceName":"BWM Gartenhütte","deviceType":"HM-Sen-MDIR-O-2","channel":"LTK0028082:1","channelName":"BWM Gartenhütte","channelType":"MOTION_DETECTOR","channelIndex":1,"datapoint":"MOTION","datapointName":"BidCos-RF.LTK0028082:1.MOTION","datapointType":"BOOL","datapointMin":false,"datapointMax":true,"datapointDefault":false,"valueStable":false,"rooms":["Garten"],"room":"Garten","functions":["Homekit"],"function":"Homekit","ts":1587971766000,"lc":1587971766000,"change":false,"cache":true,"working":false,"uncertain":false,"stable":true}}`,
  40. JsonExp: `{"Device":"BWM Gartenhütte", "Motion":false,"Time":1587971766000}`,
  41. },
  42. TestRuleStruct{
  43. RuleName: "hmBWMBright",
  44. RuleSrc: `[
  45. {"operation": "shift",
  46. "spec": {
  47. "Device": "hm.channelName",
  48. "Brightness": "hm.valueStable",
  49. "Time": "ts"
  50. }
  51. }
  52. ]`,
  53. JsonSrc: `{"val":181,"ts":1587973274220,"lc":1587973274220,"hm":{"ccu":"localhost","iface":"BidCos-RF","device":"LTK0028082","deviceName":"BWM Gartenhütte","deviceType":"HM-Sen-MDIR-O-2","channel":"LTK0028082:1","channelName":"BWM Gartenhütte","channelType":"MOTION_DETECTOR","channelIndex":1,"datapoint":"BRIGHTNESS","datapointName":"BidCos-RF.LTK0028082:1.BRIGHTNESS","datapointType":"INTEGER","datapointMin":0,"datapointMax":255,"datapointDefault":0,"valuePrevious":180,"valueStable":181,"rooms":["Garten"],"room":"Garten","functions":["Homekit"],"function":"Homekit","ts":1587973274220,"tsPrevious":1587972873227,"lc":1587973274220,"change":true,"cache":false,"uncertain":false,"stable":true}}`,
  54. JsonExp: `{"Device":"BWM Gartenhütte", "Brightness":181,"Time":1587973274220}`,
  55. },
  56. TestRuleStruct{
  57. RuleName: "hmTermTemp",
  58. RuleSrc: `[
  59. {"operation": "shift",
  60. "spec": {
  61. "Device": "hm.deviceName",
  62. "Temperature": "hm.valueStable",
  63. "Time": "ts"
  64. }
  65. }
  66. ]`,
  67. JsonSrc: `{"val":22.6,"ts":1587973561640,"lc":1587973561640,"hm":{"ccu":"localhost","iface":"BidCos-RF","device":"OEQ1670535","deviceName":"Thermostat Bad","deviceType":"HM-TC-IT-WM-W-EU","channel":"OEQ1670535:1","channelName":"HM-TC-IT-WM-W-EU OEQ1670535:1","channelType":"WEATHER_TRANSMIT","channelIndex":1,"datapoint":"TEMPERATURE","datapointName":"BidCos-RF.OEQ1670535:1.TEMPERATURE","datapointType":"FLOAT","datapointMin":-10,"datapointMax":50,"datapointDefault":0,"datapointControl":"NONE","valuePrevious":22.7,"valueStable":22.6,"rooms":["Bad"],"room":"Bad","functions":["Heizung"],"function":"Heizung","ts":1587973561640,"tsPrevious":1587973426887,"lc":1587973561640,"change":true,"cache":false,"uncertain":false,"stable":true}}`,
  68. JsonExp: `{"Device":"Thermostat Bad", "Temperature":22.6,"Time":1587973561640}`,
  69. },
  70. TestRuleStruct{
  71. RuleName: "hmTermHumi",
  72. RuleSrc: `[
  73. {"operation": "shift",
  74. "spec": {
  75. "Device": "hm.deviceName",
  76. "Humidity": "hm.valueStable",
  77. "Time": "ts"
  78. }
  79. }, {
  80. "operation": "timestamp",
  81. "spec": {
  82. "Time": {
  83. "inputFormat": "$unixext",
  84. "outputFormat": "2006-01-02T15:04:05"
  85. }
  86. }
  87. }
  88. ]`,
  89. JsonSrc: `{"val":40, "ts":1587973561647,"lc":1587973561647,"hm":{"ccu":"localhost","iface":"BidCos-RF","device":"OEQ1670535","deviceName":"Thermostat Bad","deviceType":"HM-TC-IT-WM-W-EU","channel":"OEQ1670535:1","channelName":"HM-TC-IT-WM-W-EU OEQ1670535:1","channelType":"WEATHER_TRANSMIT","channelIndex":1,"datapoint":"HUMIDITY","datapointName":"BidCos-RF.OEQ1670535:1.HUMIDITY","datapointType":"INTEGER","datapointMin":0,"datapointMax":99,"datapointDefault":0,"datapointControl":"NONE","valuePrevious":39,"valueStable":40,"rooms":["Bad"],"room":"Bad","functions":["Heizung"],"function":"Heizung","ts":1587973561647,"tsPrevious":1587973426898,"lc":1587973561647,"change":true,"cache":false,"uncertain":false,"stable":true}}`,
  90. JsonExp: `{"Device":"Thermostat Bad", "Humidity":40,"Time":"2020-04-27T09:46:01"}`,
  91. },
  92. }
  93. func TestTasmotaRule(t *testing.T) {
  94. for _, testRule := range TestingRules {
  95. err := Rules.Register("mcs", testRule.RuleName, testRule.RuleSrc)
  96. if err != nil {
  97. t.Errorf("can't transforn: %v", err)
  98. return
  99. }
  100. jsonDest, err := Rules.TransformJSON("mcs", testRule.RuleName, []byte(testRule.JsonSrc))
  101. if err != nil {
  102. t.Errorf("can't transforn: %v", err)
  103. return
  104. }
  105. areEqual, _ := checkJSONBytesEqual(jsonDest, []byte(testRule.JsonExp))
  106. if !areEqual {
  107. t.Error("Transformed data does not match expectation.")
  108. t.Log("Source: ", testRule.JsonSrc)
  109. t.Log("Expected: ", testRule.JsonExp)
  110. t.Log("Actual: ", string(jsonDest))
  111. t.FailNow()
  112. }
  113. t.Log("transformation OK.", string(jsonDest))
  114. }
  115. }
  116. func TestSimpleRule(t *testing.T) {
  117. jsonConfig := `[{
  118. "operation": "shift",
  119. "spec": {
  120. "Temperature": "DS18B20.Temperature",
  121. "TempUnit": "TempUnit"
  122. }
  123. }]`
  124. Rules.Register("mcs", "test.me", jsonConfig)
  125. jsonObject := `{
  126. "doc": {
  127. "uid": 12345,
  128. "guid": ["guid0", "guid2", "guid4"],
  129. "guidObjects": [{"id": "guid0"}, {"id": "guid2"}, {"id": "guid4"}]
  130. },
  131. "top-level-key": null
  132. }`
  133. jsonDest, err := Rules.TransformJSON("mcs", "test.me", []byte(jsonObject))
  134. if err != nil {
  135. t.Errorf("can't transforn: %v", err)
  136. return
  137. }
  138. t.Log("transformation OK.", string(jsonDest))
  139. }
  140. func TestUnknownRule(t *testing.T) {
  141. jsonObject := `{
  142. "doc": {
  143. "uid": 12345,
  144. "guid": ["guid0", "guid2", "guid4"],
  145. "guidObjects": [{"id": "guid0"}, {"id": "guid2"}, {"id": "guid4"}]
  146. },
  147. "top-level-key": null
  148. }`
  149. _, err := Rules.TransformJSON("mcs", "test.me2", []byte(jsonObject))
  150. if err != ErrRuleNotDefined {
  151. t.Errorf("something goes wrong: %v", err)
  152. return
  153. }
  154. t.Log("unknown rule throws error.")
  155. }
  156. func checkJSONBytesEqual(item1, item2 []byte) (bool, error) {
  157. var out1, out2 interface{}
  158. err := json.Unmarshal(item1, &out1)
  159. if err != nil {
  160. return false, nil
  161. }
  162. err = json.Unmarshal(item2, &out2)
  163. if err != nil {
  164. return false, nil
  165. }
  166. return reflect.DeepEqual(out1, out2), nil
  167. }