You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
5.1 KiB

  1. package main
  2. import (
  3. "git.aiterp.net/lucifer/new-server/models"
  4. "log"
  5. "strconv"
  6. "strings"
  7. "time"
  8. )
  9. type Param struct {
  10. Index int
  11. Key string
  12. Value string
  13. Operator string
  14. }
  15. func (p *Param) String() *string {
  16. if p == nil {
  17. return nil
  18. }
  19. return &p.Value
  20. }
  21. func (p *Param) TimeOfDay() *models.TimeOfDay {
  22. if p == nil {
  23. return nil
  24. }
  25. tod, err := models.ParseTimeOfDay(p.Value)
  26. if err != nil {
  27. return nil
  28. }
  29. return &tod
  30. }
  31. func (p *Param) TimeOfDayOr(fallback models.TimeOfDay) models.TimeOfDay {
  32. tod := p.TimeOfDay()
  33. if tod == nil {
  34. return fallback
  35. }
  36. return *tod
  37. }
  38. func (p *Param) StringOr(fallback string) string {
  39. if p == nil {
  40. return fallback
  41. }
  42. return p.Value
  43. }
  44. func (p *Param) Int() *int {
  45. if p == nil {
  46. return nil
  47. }
  48. n, err := strconv.Atoi(p.Value)
  49. if err != nil {
  50. return nil
  51. }
  52. return &n
  53. }
  54. func (p *Param) IntOr(other int) int {
  55. val := p.Int()
  56. if val == nil {
  57. return other
  58. }
  59. return *val
  60. }
  61. func (p *Param) Float() *float64 {
  62. if p == nil {
  63. return nil
  64. }
  65. n, err := strconv.ParseFloat(p.Value, 64)
  66. if err != nil {
  67. return nil
  68. }
  69. return &n
  70. }
  71. func (p *Param) Bool() *bool {
  72. if p == nil {
  73. return nil
  74. }
  75. v := strings.ToLower(p.Value)
  76. if v == "yes" || v == "true" || v == "on" {
  77. r := true
  78. return &r
  79. } else if v == "no" || v == "false" || v == "off" {
  80. r := false
  81. return &r
  82. }
  83. return nil
  84. }
  85. type Params []Param
  86. func (p Params) Get(key interface{}) *Param {
  87. switch key := key.(type) {
  88. case string:
  89. for _, p := range p {
  90. if p.Key == key {
  91. return &p
  92. }
  93. }
  94. case int:
  95. for _, p := range p {
  96. if p.Index == key {
  97. return &p
  98. }
  99. }
  100. default:
  101. log.Panicf("Incorrect key type %T", key)
  102. }
  103. return nil
  104. }
  105. func (p Params) Subset(prefix string) Params {
  106. if len(p) == 0 {
  107. return Params{}
  108. }
  109. if len(prefix) > 0 && !strings.HasSuffix(prefix, ".") {
  110. prefix += "."
  111. }
  112. res := make(Params, 0, len(p))
  113. for _, param := range p {
  114. if param.Index == -1 && strings.HasPrefix(param.Key, prefix) {
  115. res = append(res, Param{Index: -1, Key: param.Key[len(prefix):], Value: param.Value, Operator: param.Operator})
  116. }
  117. }
  118. return res
  119. }
  120. func (p Params) StringMap() map[string]string {
  121. res := make(map[string]string)
  122. for _, param := range p {
  123. if param.Index == -1 {
  124. res[param.Key] = param.Value
  125. }
  126. }
  127. return res
  128. }
  129. func (p Params) StringPtrMap() map[string]*string {
  130. res := make(map[string]*string)
  131. for _, param := range p {
  132. if param.Index == -1 {
  133. if param.Value == "NULL" {
  134. res[param.Key] = nil
  135. } else {
  136. res[param.Key] = &param.Value
  137. }
  138. }
  139. }
  140. return res
  141. }
  142. func (p Params) Strings(minIndex int) []string {
  143. res := make([]string, 0, len(p))
  144. for _, param := range p {
  145. if param.Index >= minIndex {
  146. res = append(res, param.Value)
  147. }
  148. }
  149. return res
  150. }
  151. func (p Params) EventConditions() map[string]models.EventCondition {
  152. ecMap := make(map[string]models.EventCondition, len(p))
  153. for _, param := range p {
  154. element, ok := ecMap[param.Key]
  155. if !ok {
  156. element = models.EventCondition{}
  157. }
  158. switch param.Operator {
  159. case "<":
  160. element.LT = param.Value
  161. case "<=":
  162. element.LTE = param.Value
  163. case ">=":
  164. element.GTE = param.Value
  165. case ">":
  166. element.GT = param.Value
  167. default:
  168. element.EQ = param.Value
  169. }
  170. ecMap[param.Key] = element
  171. }
  172. return ecMap
  173. }
  174. func (p Params) DeviceState(prefix string) models.NewDeviceState {
  175. return models.NewDeviceState{
  176. Power: p.Get(prefix + "power").Bool(),
  177. Color: p.Get(prefix + "color").String(),
  178. Intensity: p.Get(prefix + "intensity").Float(),
  179. Temperature: p.Get(prefix + "temperature").Int(),
  180. }
  181. }
  182. func (p Params) SceneAssignment(prefix string) *models.DeviceSceneAssignment {
  183. if p.Get(prefix+"scene") == nil {
  184. return nil
  185. }
  186. return &models.DeviceSceneAssignment{
  187. SceneID: p.Get(prefix+"scene").IntOr(-1),
  188. Group: p.Get(prefix+"scene.group").StringOr(time.Now().Format(time.RFC3339)),
  189. DurationMS: int64(p.Get(prefix+"scene.duration").IntOr(0)),
  190. }
  191. }
  192. type Command struct {
  193. Name string
  194. Params Params
  195. }
  196. func parseCommand(args []string) Command {
  197. if len(args) == 0 {
  198. return Command{Name: "help"}
  199. }
  200. cmd := Command{
  201. Name: args[0],
  202. Params: make(Params, 0, len(args)-1),
  203. }
  204. nextIndex := 0
  205. for _, arg := range args[1:] {
  206. kvle := strings.SplitN(arg, "<=", 2)
  207. kvge := strings.SplitN(arg, ">=", 2)
  208. kvl := strings.SplitN(arg, "<", 2)
  209. kvg := strings.SplitN(arg, ">", 2)
  210. kve := strings.SplitN(arg, "=", 2)
  211. if len(kvle) == 2 {
  212. cmd.Params = append(cmd.Params, Param{Index: -1, Key: kvle[0], Value: kvle[1], Operator: "<="})
  213. } else if len(kvge) == 2 {
  214. cmd.Params = append(cmd.Params, Param{Index: -1, Key: kvge[0], Value: kvge[1], Operator: ">="})
  215. } else if len(kvl) == 2 {
  216. cmd.Params = append(cmd.Params, Param{Index: -1, Key: kvl[0], Value: kvl[1], Operator: "<"})
  217. } else if len(kvg) == 2 {
  218. cmd.Params = append(cmd.Params, Param{Index: -1, Key: kvg[0], Value: kvg[1], Operator: ">"})
  219. } else if len(kve) == 2 {
  220. cmd.Params = append(cmd.Params, Param{Index: -1, Key: kve[0], Value: kve[1], Operator: "="})
  221. } else {
  222. cmd.Params = append(cmd.Params, Param{Index: nextIndex, Value: arg})
  223. nextIndex += 1
  224. }
  225. }
  226. return cmd
  227. }