github.com/simpleiot/simpleiot@v0.18.3/frontend/src/Components/NodeSerialDev.elm (about)

     1  module Components.NodeSerialDev exposing (view)
     2  
     3  import Api.Node as Node
     4  import Api.Point as Point
     5  import Components.NodeOptions exposing (NodeOptions, oToInputO)
     6  import Dict exposing (Dict)
     7  import Element exposing (..)
     8  import Element.Background as Background
     9  import Element.Border as Border
    10  import Element.Font as Font
    11  import FormatNumber exposing (format)
    12  import FormatNumber.Locales exposing (Decimals(..), usLocale)
    13  import Round
    14  import Time
    15  import UI.Icon as Icon
    16  import UI.NodeInputs as NodeInputs
    17  import UI.Style as Style
    18  import UI.ViewIf exposing (viewIf)
    19  import Utils.Iso8601 exposing (toDateTimeString)
    20  
    21  
    22  horizontalRule : Element msg
    23  horizontalRule =
    24      el
    25          [ width fill
    26          , height (px 1)
    27          , Border.color (Element.rgb 0.5 0.5 0.5)
    28          , Border.widthEach { bottom = 2, top = 0, left = 0, right = 0 }
    29          ]
    30          Element.none
    31  
    32  
    33  view : NodeOptions msg -> Element msg
    34  view o =
    35      let
    36          disabled =
    37              Point.getBool o.node.points Point.typeDisabled ""
    38  
    39          connected =
    40              Point.getBool o.node.points Point.typeConnected ""
    41  
    42          summaryBackground =
    43              if disabled || not connected then
    44                  Style.colors.ltgray
    45  
    46              else
    47                  Style.colors.none
    48      in
    49      column
    50          [ width fill
    51          , Border.widthEach { top = 2, bottom = 0, left = 0, right = 0 }
    52          , Border.color Style.colors.black
    53          , spacing 6
    54          ]
    55      <|
    56          wrappedRow [ spacing 10, Background.color summaryBackground ]
    57              [ Icon.serialDev
    58              , text <|
    59                  Point.getText o.node.points Point.typeDescription ""
    60              , viewIf disabled <| text "(disabled)"
    61              , viewIf (not connected) <| text "(not connected)"
    62              ]
    63              :: (if o.expDetail then
    64                      let
    65                          labelWidth =
    66                              180
    67  
    68                          opts =
    69                              oToInputO o labelWidth
    70  
    71                          textInput =
    72                              NodeInputs.nodeTextInput opts "0"
    73  
    74                          numberInput =
    75                              NodeInputs.nodeNumberInput opts "0"
    76  
    77                          counterWithReset =
    78                              NodeInputs.nodeCounterWithReset opts "0"
    79  
    80                          checkboxInput =
    81                              NodeInputs.nodeCheckboxInput opts "0"
    82  
    83                          optionInput =
    84                              NodeInputs.nodeOptionInput opts "0"
    85  
    86                          button =
    87                              NodeInputs.nodeButtonActionText opts "0"
    88  
    89                          log =
    90                              Point.getText o.node.points Point.typeLog "0"
    91  
    92                          rate =
    93                              Point.getValue o.node.points Point.typeRate "0"
    94  
    95                          rateS =
    96                              String.fromFloat (Round.roundNum 0 rate)
    97  
    98                          rateHR =
    99                              Point.getValue o.node.points Point.typeRateHR "0"
   100  
   101                          rateHRS =
   102                              String.fromFloat (Round.roundNum 0 rateHR)
   103  
   104                          download =
   105                              Point.getText o.node.points Point.typeDownload "0"
   106  
   107                          downloading =
   108                              String.length download > 0
   109  
   110                          progress =
   111                              round <| Point.getValue o.node.points Point.typeProgress "0"
   112  
   113                          files =
   114                              List.filter
   115                                  (\n ->
   116                                      n.node.typ == Node.typeFile
   117                                  )
   118                                  o.children
   119                      in
   120                      [ textInput Point.typeDescription "Description" ""
   121                      , textInput Point.typePort "Port" "/dev/ttyUSB0"
   122                      , textInput Point.typeBaud "Baud" "9600"
   123                      , numberInput Point.typeMaxMessageLength "Max Msg Len"
   124                      , textInput Point.typeHRDest "HR Dest Node" ""
   125                      , checkboxInput Point.typeSyncParent "Sync parent node"
   126                      , numberInput Point.typeDebug "Debug level (0-9)"
   127                      , checkboxInput Point.typeDisabled "Disabled"
   128                      , horizontalRule
   129                      , counterWithReset Point.typeErrorCount Point.typeErrorCountReset "Error Count"
   130                      , counterWithReset Point.typeRx Point.typeRxReset "Rx count"
   131                      , counterWithReset Point.typeTx Point.typeTxReset "Tx count"
   132                      , counterWithReset Point.typeErrorCountHR Point.typeErrorCountResetHR "HR err count"
   133                      , counterWithReset Point.typeHrRx Point.typeHrRxReset "HR Rx count"
   134                      , text <| "  Rate (pts/sec): " ++ rateS
   135                      , text <| "  Rate HR (pkts/sec): " ++ rateHRS
   136                      , text <| "  Last log: " ++ log
   137                      , viewIf (List.length files > 0) <| horizontalRule
   138                      , viewIf (List.length files > 0 && not downloading) <|
   139                          optionInput Point.typeDownload
   140                              "Download file"
   141                              (List.map
   142                                  (\n ->
   143                                      let
   144                                          description =
   145                                              Point.getText n.node.points Point.typeDescription "0"
   146  
   147                                          filename =
   148                                              Point.getText n.node.points Point.typeName "0"
   149                                      in
   150                                      ( filename, description ++ ": " ++ filename )
   151                                  )
   152                                  files
   153                              )
   154                      , viewIf downloading <|
   155                          text <|
   156                              "Downloading: "
   157                                  ++ download
   158                      , viewIf downloading <|
   159                          text <|
   160                              "Progress: "
   161                                  ++ String.fromInt progress
   162                                  ++ " %"
   163                      , viewIf downloading <|
   164                          button Point.typeDownload "" "Cancel download" Style.colors.red
   165                      , horizontalRule
   166                      , viewPoints o.zone <| Point.filterSpecialPoints <| List.sortWith Point.sort o.node.points
   167                      , NodeInputs.nodeKeyValueInput opts Point.typeTag "Tags" "Add Tag"
   168                      ]
   169  
   170                  else
   171                      []
   172                 )
   173  
   174  
   175  viewPoints : Time.Zone -> List Point.Point -> Element msg
   176  viewPoints z pts =
   177      let
   178          formaters =
   179              metricFormaters z
   180  
   181          fm =
   182              formatMetric formaters
   183      in
   184      table [ padding 7 ]
   185          { data = Point.filterTombstone pts |> List.map fm
   186          , columns =
   187              let
   188                  cell =
   189                      el [ paddingXY 15 5, Border.width 1 ]
   190              in
   191              [ { header = cell <| el [ Font.bold, centerX ] <| text "Point"
   192                , width = fill
   193                , view = \m -> cell <| text m.desc
   194                }
   195              , { header = cell <| el [ Font.bold, centerX ] <| text "Value"
   196                , width = fill
   197                , view = \m -> cell <| el [ alignRight ] <| text m.value
   198                }
   199              ]
   200          }
   201  
   202  
   203  formatMetric : Dict String MetricFormat -> Point.Point -> { desc : String, value : String }
   204  formatMetric formaters p =
   205      case Dict.get p.typ formaters of
   206          Just f ->
   207              { desc = f.desc p, value = f.vf p }
   208  
   209          Nothing ->
   210              Point.renderPoint2 p
   211  
   212  
   213  type alias MetricFormat =
   214      { desc : Point.Point -> String
   215      , vf : Point.Point -> String
   216      }
   217  
   218  
   219  metricFormaters : Time.Zone -> Dict String MetricFormat
   220  metricFormaters z =
   221      let
   222          toTimeWithZone =
   223              toTime z
   224      in
   225      Dict.fromList
   226          [ ( "metricAppAlloc", { desc = descS "App Memory Alloc", vf = toMiB } )
   227          , ( "metricAppNumGoroutine", { desc = descS "App Goroutine Count", vf = toWhole } )
   228          , ( "metricProcCPUPercent", { desc = descS "Proc CPU %", vf = toPercent } )
   229          , ( "metricProcMemPercent", { desc = descS "Proc Mem %", vf = toPercent } )
   230          , ( "metricProcMemRSS", { desc = descS "Proc Mem RSS", vf = toMiB } )
   231          , ( "host", { desc = descKey "Host", vf = toText } )
   232          , ( "hostBootTime", { desc = descS "Host Boot Time", vf = toTimeWithZone } )
   233          , ( "metricSysCPUPercent", { desc = descS "Sys CPU %", vf = toPercent } )
   234          , ( "metricSysDiskUsedPercent", { desc = descKey "Disk Used %", vf = toPercent } )
   235          , ( "metricSysLoad", { desc = descKey "Load", vf = \p -> Round.round 2 p.value } )
   236          , ( "metricSysMemUsedPercent", { desc = descS "Memory used %", vf = toPercent } )
   237          , ( "metricSysMem", { desc = descKey "Memory", vf = toMiB } )
   238          , ( "metricSysNetBytesRecv", { desc = descKey "Net RX", vf = toWhole } )
   239          , ( "metricSysNetBytesSent", { desc = descKey "Net TX", vf = toWhole } )
   240          , ( "metricSysUptime", { desc = descKey "Uptime", vf = toWhole } )
   241          ]
   242  
   243  
   244  toMiB : Point.Point -> String
   245  toMiB p =
   246      format { usLocale | decimals = Exact 1 } (p.value / (1024 * 1024))
   247  
   248  
   249  toPercent : Point.Point -> String
   250  toPercent p =
   251      Round.round 1 p.value ++ " %"
   252  
   253  
   254  toWhole : Point.Point -> String
   255  toWhole p =
   256      format { usLocale | decimals = Exact 0 } p.value
   257  
   258  
   259  toText : Point.Point -> String
   260  toText p =
   261      if p.text == "" then
   262          " "
   263  
   264      else
   265          p.text
   266  
   267  
   268  toTime : Time.Zone -> Point.Point -> String
   269  toTime z p =
   270      let
   271          t =
   272              Time.millisToPosix (round p.value * 1000)
   273      in
   274      toDateTimeString z t
   275  
   276  
   277  descS : String -> Point.Point -> String
   278  descS d _ =
   279      d
   280  
   281  
   282  descKey : String -> Point.Point -> String
   283  descKey d p =
   284      d ++ " " ++ p.key