updates
[mTask.git] / Devices / mTaskDevice.icl
1 implementation module Devices.mTaskDevice
2
3 from StdFunc import flip
4 import Generics.gCons
5 import mTaskInterpret
6 import iTasks
7 import iTasksTTY
8 import TTY
9 import qualified Data.Map as DM
10 import Utils.SDS
11
12 import GenBimap
13 import Devices.mTaskSerial
14 import Devices.mTaskTCP
15 import iTasks._Framework.Store
16 import iTasks.UI.Definition, iTasks.UI.Editor, iTasks.UI.Editor.Builtin, iTasks.UI.Editor.Common, iTasks.UI.Layout.Default, iTasks.UI.Layout.Common
17
18 from Data.Func import $
19
20 derive class iTask MTaskDevice, MTaskResource, MTaskMSGRecv, MTaskMSGSend
21 derive conses MTaskResource, TTYSettings, BaudRate, Parity, ByteSize, TCPSettings
22 derive consName MTaskResource, TTYSettings, BaudRate, Parity, ByteSize, TCPSettings
23
24 instance == MTaskDevice where
25 (==) a b = a.deviceChannels == b.deviceChannels
26
27 channels :: MTaskDevice -> Shared Channels
28 channels d = memoryShare d.deviceChannels ([], [], False)
29
30 startupDevices :: Task [MTaskDevice]
31 startupDevices = upd (map reset) deviceStore
32 where reset d = {d & deviceTask=Nothing, deviceTasks=[], deviceError=Nothing}
33
34 makeDevice :: String MTaskResource -> Task MTaskDevice
35 makeDevice name res = get randomInt @ \rand->{MTaskDevice
36 |deviceChannels=name +++ toString rand
37 ,deviceName=name
38 ,deviceTasks=[]
39 ,deviceTask=Nothing
40 ,deviceError=Nothing
41 ,deviceData=res}
42
43 getSynFun :: MTaskResource -> ((Shared Channels) -> Task ())
44 getSynFun (TCPDevice t) = synFun t
45 getSynFun (SerialDevice t) = synFun t
46
47 addDevice :: (Shared [MTaskDevice]) (MTaskDevice (Shared Channels) -> Task ()) -> Task String
48 addDevice devices processFun
49 = enterChoice "Device type" [] (map consName{|*|} deviceTypes)
50 >&^ \sh->whileUnchanged sh $ \mty->case mty of
51 Nothing = viewInformation "No type selected yet" [] ""
52 Just ty = enterInformation "Name" [] -&&- deviceSettings ty
53 >>= \(name, settings)->makeDevice name settings
54 >>= \dev->upd (\l->[dev:l]) devices
55 >>| connectDevice processFun dev
56 @! ""
57 where
58 deviceSettings "SerialDevice" = getmTaskSerialDevice
59 deviceSettings "TCPDevice" = getmTaskTCPDevice
60
61 deviceTypes :: [MTaskResource]
62 deviceTypes = conses{|*|}
63
64 connectDevice :: (MTaskDevice (Shared Channels) -> Task ()) MTaskDevice -> Task ()
65 connectDevice pf d = let ch = channels d in appendTopLevelTask 'DM'.newMap True
66 (pf d ch -||- catchAll (getSynFun d.deviceData ch) errorHandle)
67 >>= \tid->withDevices d (\d->{d&deviceTask=Just tid,deviceError=Nothing}) @! ()
68 where
69 errorHandle e = withDevices d (\d->{d&deviceTask=Nothing,deviceError=Just e})
70
71 manageDevices :: (MTaskDevice (Shared Channels) -> Task ()) [MTaskDevice] -> Task ()
72 manageDevices processFun ds = anyTask [
73 addDevice deviceStore processFun <<@ Title "Add new device" @! ():
74 [viewDevice processFun d
75 <<@ Title d.deviceName\\d<-ds]]
76 <<@ ArrangeWithTabs @! ()
77
78 viewDevice :: (MTaskDevice (Shared Channels) -> Task ()) MTaskDevice -> Task ()
79 viewDevice pf d = forever $ anyTask
80 [viewInformation "Device settings" [] d @! ()
81 ,viewSharedInformation "Channels" [ViewAs dropEmpty] (channels d) @! ()
82 ,forever $
83 enterChoice "Delete task on device" [ChooseFromGrid id] d.deviceTasks
84 >>* [OnAction (Action "Delete") $ ifValue (\t->t.ident <> -1) (deviceTaskDelete d)]
85 @! ()
86 ] <<@ ArrangeHorizontal
87 >>* [OnAction (Action "Delete Device") (always $ deleteDevice d):
88 if (isJust d.deviceTask) []
89 [OnAction (Action "Connect") (always $ connectDevice pf d)]]
90 where
91 dropEmpty (r,s,ss) = (filter ((=!=)MTEmpty) r,s,ss)
92
93 deleteDevice :: MTaskDevice -> Task ()
94 deleteDevice d = upd (\(r,s,ss)->(r,s,True)) (channels d)
95 >>| maybe (treturn ()) (flip removeTask topLevelTasks) d.deviceTask
96 >>| upd (filter ((==)d)) deviceStore
97 @! ()
98
99 sendToDevice :: String (Main (ByteCode () Stmt)) (MTaskDevice, MTaskInterval) -> Task ()
100 sendToDevice wta mTask (device, timeout) =
101 get bcStateStore @ toMessages timeout o toRealByteCode (unMain mTask)
102 >>= \(msgs, st1)->set st1 bcStateStore @ toSDSRecords
103 >>= \sdss->set sdss sdsStore//MTaskShareaddToSDSShare
104 >>| makeShares sdss
105 >>| sendMessage device msgs
106 >>| makeTask wta -1
107 >>= withDevices device o addTask
108 @! ()
109 where
110 sharename i = device.deviceChannels +++ "-" +++ toString i
111 toSDSRecords st = [{MTaskShare |
112 initValue=toInt d1*265 + toInt d2,
113 withTask=wta,
114 identifier=i,
115 realShare="mTaskSDS-" +++ toString i}
116 \\(i,[d1,d2])<-st.sdss]
117 makeShares = foldr (\sh t->set sh.initValue (getSDSStore sh) >>| t) (treturn ())
118
119 addTask :: MTaskTask MTaskDevice -> MTaskDevice
120 addTask task device = {device & deviceTasks=[task:device.deviceTasks]}
121
122 sendMessage :: MTaskDevice [MTaskMSGSend] -> Task ()
123 sendMessage dev msgs = upd (\(r,s,ss)->(r,msgs++s,ss)) (channels dev) @! ()
124
125 withDevices :: MTaskDevice (MTaskDevice -> MTaskDevice) -> Task ()
126 withDevices a trans = upd (map \b->if (b == a) (trans b) b) deviceStore @! ()
127
128 deviceTaskAcked :: MTaskDevice Int -> Task ()
129 deviceTaskAcked dev i
130 = withDevices dev (\d->{d&deviceTasks=ackFirst d.deviceTasks})
131 where
132 ackFirst :: [MTaskTask] -> [MTaskTask]
133 ackFirst [] = []
134 ackFirst [t:ts] = if (t.ident == -1)
135 [{t & ident=i}:ts] [t:ackFirst ts]
136
137 deviceTaskDelete :: MTaskDevice MTaskTask -> Task ()
138 deviceTaskDelete dev task = sendMessage dev [MTTaskDel task.ident]
139
140 deviceTaskDeleteAcked :: MTaskDevice Int -> Task ()
141 deviceTaskDeleteAcked d i = withDevices d $ deleteTask
142 where deleteTask d = {d & deviceTasks=[s\\s<-d.deviceTasks | i <> s.ident]}