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.

265 lines
4.7 KiB

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