move generics to a different directory, add task sending framework
[mTask.git] / miTask.icl
index 767cd98..738f8c2 100644 (file)
@@ -8,8 +8,11 @@ import mTask
 
 from Text import class Text(startsWith,concat,split,join), instance Text String
 
 
 from Text import class Text(startsWith,concat,split,join), instance Text String
 
+import qualified Data.Map as DM
+
 from Data.Func import $
 import Data.Tuple
 from Data.Func import $
 import Data.Tuple
+import Data.List
 import System.Directory
 
 import iTasks.UI.Definition
 import System.Directory
 
 import iTasks.UI.Definition
@@ -19,17 +22,44 @@ import iTasks._Framework.TaskServer
 import iTasks._Framework.IWorld
 import iTasks._Framework.Store
 
 import iTasks._Framework.IWorld
 import iTasks._Framework.Store
 
+
 import TTY
 
 derive class iTask Queue, TTYSettings, Parity, BaudRate, ByteSize
 derive class iTask MTaskMSGRecv, MTaskMSGSend, SerTCP, UserLED
 
 import TTY
 
 derive class iTask Queue, TTYSettings, Parity, BaudRate, ByteSize
 derive class iTask MTaskMSGRecv, MTaskMSGSend, SerTCP, UserLED
 
-:: SerTCP = Serial | TCP
 :: *Resource | TTYd !*TTY
 :: *Resource | TTYd !*TTY
+:: Channels :== ([MTaskMSGRecv], [MTaskMSGSend], Bool)
+
+:: SerTCP = SerialDevice | TCPDevice
+:: MTaskDevice = {
+               deviceConnected :: Maybe String,
+               deviceName :: String,
+               deviceTasks :: [(String, Int)]
+       }
+:: MTaskShare = {
+               identifier :: Int,
+               realShare :: String
+       }
 
 Start :: *World -> *World
 
 Start :: *World -> *World
-Start world = startEngine mTaskTask world
-//Start world = startEngine mTaskTask world
+Start world = startEngine (mTaskManager
+       >>* [OnAction (Action "Shutdown") (always $ shutDown)]) world
+
+memoryShare :: String a -> Shared a | iTask a
+memoryShare s d = sdsFocus s $ memoryStore "" $ Just d
+
+deviceStore :: Shared [MTaskDevice]
+deviceStore = memoryShare "mTaskDevices" []
+
+sdsStore :: Shared [MTaskShare]
+sdsStore = memoryShare "mTaskShares" []
+
+bcStateStore :: Shared BCState
+bcStateStore = memoryShare "mTaskBCState" zero
+
+mTaskTaskStore :: Shared [String]
+mTaskTaskStore = memoryShare "mTaskTasks" ["ledder", "ledon", "ledoff"]
 
 bc :: Main (ByteCode () Stmt)
 bc = sds \x=1 In sds \pinnetje=1 In {main =
 
 bc :: Main (ByteCode () Stmt)
 bc = sds \x=1 In sds \pinnetje=1 In {main =
@@ -55,88 +85,188 @@ bc2 d = {main = ledOn d}
 bc3 :: UserLED -> Main (ByteCode () Stmt)
 bc3 d = {main = ledOff d}
 
 bc3 :: UserLED -> Main (ByteCode () Stmt)
 bc3 d = {main = ledOff d}
 
+:: MTaskDeviceStatus = {connected :: Bool, name :: String, tasks :: [(String, Int)]}
+derive class iTask MTaskDeviceStatus, MTaskDevice, MTaskShare, BCState
 
 
-withDevice :: ((Shared ([MTaskMSGRecv],[MTaskMSGSend],Bool)) -> Task a) -> Task a | iTask a
-withDevice t = withShared ([], [], False) \ch->
-               enterInformation "Type" []
-       >>= \ty->case ty of
-               TCP = (enterInformation "Host" [] -&&- enterInformation "Port" [])
-                       >>= \(port,host)->t ch -|| syncNetworkChannel host port ch
-               Serial = accWorld getDevices
-                       >>= \dl->(enterChoice "Device" [] dl -&&- updateInformation "Settings" [] zero)
-                       >>= \(dev,set)->t ch -|| syncSerialChannel dev set ch
+mTaskManager :: Task ()
+mTaskManager = anyTask 
+               [ viewmTasks @! ()
+               , viewShares
+               , whileUnchanged deviceStore viewDevices
+               ] <<@ ApplyLayout layout
        where
        where
-               getDevices :: !*World -> *(![String], !*World)
-               getDevices w = case readDirectory "/dev" w of
-                       (Error (errcode, errmsg), w) = abort errmsg
-                       (Ok entries, w) = (map ((+++) "/dev/") (filter isTTY entries), w)
+               isValue (Value _ _) = True
+               isValue _                       = False
+
+               viewmTasks = listmTasks
+                       >&^ \sh->whileUnchanged sh $ \mi->case mi of
+                               Nothing = viewInformation "No task selected" [] ()
+                               Just mTaskTask = get deviceStore
+                                       >>= \devices->case devices of
+                                               [] = viewInformation "No devices yet" [] ()
+                                               ds = sendmTask mTaskTask ds @! ()
+                       where
+                               listmTasks :: Task String
+                               listmTasks = enterChoiceWithShared "Available mTasks" [ChooseFromList id] mTaskTaskStore
+
+                               sendmTask mTaskId ds = enterChoice "Choose Device" [ChooseFromDropdown (\t->t.deviceName)] ds <<@ Title mTaskId
+                                       >>* [OnAction (Action "Send") (withValue $ sendToDevice mTaskId)]
+
+                               sendToDevice mTask device = Just $ viewInformation "" [] device
+                                       
+                                       
+
+               layout = sequenceLayouts
+                       [ arrangeWithSideBar 0 LeftSide 260 True
+                       , arrangeSplit Vertical True
+                       ]
+
+               viewShares :: Task ()
+               viewShares = forever $
+                               enterChoiceWithShared "Shares" [ChooseFromList sdsvw] sdsShare
+                       >>* [OnValue $ withValue $ Just o updateShare]
+                       >>* [OnAction (Action "Back") (const $ Just $ treturn ())]
                        where
                        where
+                               sdsvw (k, v) = concat ["SDS ", toString k, ": ", toString v]
+                               updateShare (k, v) = (viewInformation "Key" [] k
+                                       ||- updateInformation "Value" [] v)
+                                       
+
+               viewDevices :: [MTaskDevice] -> Task ()
+               viewDevices ds = anyTask [
+                               addDevice deviceStore <<@ Title "Add new device" @! ():
+                                       [viewDevice d <<@ Title d.deviceName\\d<-ds]]
+                       <<@ ArrangeWithTabs @! ()
+               
+               viewDevice :: MTaskDevice -> Task ()
+               viewDevice d = (viewInformation "Device settings" [] d 
+                               ||- (case d.deviceConnected of
+                                       Just s = viewSharedInformation "Channels" [] (channels d.deviceName) @! ()
+                                       Nothing = viewInformation "No channels yet" [] "" @! ()
+                               )) <<@ ArrangeHorizontal
+
+               channels :: String -> Shared Channels
+               channels s = sdsFocus s $ memoryStore "" $ Just ([], [], False)
+
+               sdsShare :: Shared [(Int, Int)]
+               sdsShare = sdsFocus "mTaskSDSs" $ memoryStore "" $ Just [(1, 1)]
+
+               addDevice :: (Shared [MTaskDevice]) -> Task ()
+               addDevice devices = enterInformation "Device type and name" []
+                       >>= \(name, ty)->get randomInt @ ((+++) name o toString)
+                       >>= \realname->let ch = channels realname in case ty of
+                               TCPDevice = enterInformation "Hostname and port" []
+                                       >>= \(host, port)->cont realname name ||- syncNetworkChannel host port ch
+                               SerialDevice = accWorld getDevices
+                                       >>= \dl->(enterChoice "Device" [] dl -&&- updateInformation "Settings" [] zero)
+                                       >>= \(device, settings)->cont realname name ||- syncSerialChannel device settings ch
+                       where
+                               cont rn nm = (upd (\l->[dev rn nm:l]) devices >>| addDevice devices)
+                               dev rn nm = {deviceConnected=Just rn,deviceName=nm,deviceTasks=[]}
+
+                               getDevices :: !*World -> *(![String], !*World)
+                               getDevices w = case readDirectory "/dev" w of
+                                       (Error (errcode, errmsg), w) = abort errmsg
+                                       (Ok entries, w) = (map ((+++) "/dev/") (filter isTTY entries), w)
+
                                isTTY s = not (isEmpty (filter (flip startsWith s) prefixes))
                                prefixes = ["ttyS", "ttyACM", "ttyUSB", "tty.usbserial"]
 
                                isTTY s = not (isEmpty (filter (flip startsWith s) prefixes))
                                prefixes = ["ttyS", "ttyACM", "ttyUSB", "tty.usbserial"]
 
-mTaskTask :: Task ()
-mTaskTask = let (msgs, sdsShares) = makeMsgs 1000 bc in
-       withDevice \ch->
-                       sendMsg msgs ch
-               ||- processMessages ch messageShare sdsShares
-               ||- forever (enterChoice "Choose led to enable" [] [LED1, LED2, LED3]
-                               >>= \p->sendMsg (fst (makeMsgs 0 (bc2 p))) ch)
-               ||- forever (enterChoice "Choose led to disable" [] [LED1, LED2, LED3]
-                               >>= \p->sendMsg (fst (makeMsgs 0 (bc3 p))) ch)
-               ||- viewSharedInformation "channels" [ViewAs lens] ch
-               ||- viewSharedInformation "messages" [] messageShare
-               ||- viewSh sdsShares ch
-               >>* [OnAction ActionFinish (always shutDown)]
-       where
-               messageShare :: Shared [String]
-               messageShare = sharedStore "mTaskMessagesRecv" []
+//             connectDevice :: [MTaskDevice] -> Task ()
+//             connectDevice [] = treturn ()
+//             connectDevice [d:ds] = (case d.deviceConnected of
+//                     (Just sh) = viewSharedInformation "Buffers" [] sh @! ()
+//                     Nothing = viewInformation ("Connect " +++ d.deviceName) [] "" >>* [
+//                             OnAction (Action "connect") (const $ Just $ connect d)]
+//                     ) -|| connectDevice ds
 
 
-               processMessages ch msgs sdss = forever (watch ch
-                       >>* [OnValue (ifValue (not o isEmpty o fst3) (process ch))])
-                       where
-                               process :: (Shared ([MTaskMSGRecv],[MTaskMSGSend],Bool)) ([MTaskMSGRecv],[MTaskMSGSend],Bool) -> Task ()
-                               process ch (r,_,_) = upd (appFst3 (const [])) ch >>| process` r
-                                       where
-                                               process` = foldr (\r t->updateSDSs sdss msgs r >>| t) (return ())
-
-               makeMsgs :: Int (Main (ByteCode () Stmt)) -> ([MTaskMSGSend], [(Int, Shared Int)])
-               makeMsgs timeout bc
-               # (msgs, st) = toMessages timeout (toRealByteCode (unMain bc))
-               = (msgs, map f st.sdss)
-                       where 
-                               f (i,d) = (i, sharedStore ("mTaskSDS-" +++ toString i) (dd d))
-                               dd [x,y] = toInt x*265 + toInt y
-
-               updateSDSs :: [(Int, Shared Int)] (Shared [String]) MTaskMSGRecv -> Task ()
-               updateSDSs [(id, sh):xs] m n=:(MTPub i d)
-               | id == i = set ((toInt d.[0])*265 + toInt d.[1]) sh @! ()
-               = updateSDSs xs m n
-               updateSDSs _ m mtm = case mtm of
-                       MTMessage s = upd (\l->take 5 [s:l]) m @! ()
-                       mta=:(MTTaskAck _) = upd (\l->take 5 [toString mta:l]) m @! ()
-                       //TODO other recv msgs
-                       _ = return ()
-
-               lens :: ([MTaskMSGRecv], [MTaskMSGSend],Bool) -> ([String], [String])
-               lens (r,s,_) = (map toString r, map toString s)
-
-               viewSh :: [(Int, Shared Int)] (Shared ([MTaskMSGRecv],[MTaskMSGSend],Bool)) -> Task ()
-               viewSh [] ch = return ()
-               viewSh [(i, sh):xs] ch
-               # sharename = "SDS-" +++ toString i
-               = (
-                               viewSharedInformation ("SDS-" +++ toString i) [] sh ||-
-                               forever (
-                                       enterInformation sharename []
-                                       >>* [OnAction ActionOk 
-                                                       (ifValue (\j->j>=1 && j <= 3) 
-                                                       (\c->set c sh
-                                                               >>= \_->sendMsg (toSDSUpdate i c) ch
-                                                               @! ()
-                                                       )
-                                               )]
-                               )
-                       ) ||- viewSh xs ch
+               deviceviewer :: [MTaskDevice] -> [MTaskDeviceStatus]
+               deviceviewer ds = [{MTaskDeviceStatus | name = d.deviceName,
+                       connected = if (isNothing d.deviceConnected) False True,
+                       tasks = d.deviceTasks}\\d<-ds]
+       
+//             showTabbed :: [MTaskDevice] -> Task ()
+//             showTabbed [] = viewInformation "" [] "No devices yet" @! ()
+//             showTabbed [l:ls] = foldr (\e es->manageDevice e ||- es) (manageDevice l) ls
+//
+//             manageDevice :: MTaskDevice -> Task ()
+//             manageDevice md = 
+//                             either viewTCP viewSer md.deviceSettings
+//                     ||- maybe
+//                             (treturn () >>* [OnAction (Action "Connect") (always shutDown)] @! ())
+//                             (\b->viewSharedInformation "Buffers" [] b @! ())
+//                             md.deviceConnected
+//                     <<@ ArrangeVertical
+
+               mapPar :: (a -> Task a) [a] -> Task ()
+               mapPar f l = foldr1 (\x y->f x ||- y) l <<@ ArrangeWithTabs @! ()
+               allAtOnce t = foldr1 (||-) t @! ()
+               //allAtOnce = (flip (@!) ()) o foldr1 (||-)
+
+
+//mTaskTask :: Task ()
+//mTaskTask = let (msgs, sdsShares) = makeMsgs 1000 bc in
+//     withDevice \ch->
+//                     sendMsg msgs ch
+//             ||- processMessages ch messageShare sdsShares
+//             ||- forever (enterChoice "Choose led to enable" [] [LED1, LED2, LED3]
+//                             >>= \p->sendMsg (fst (makeMsgs 0 (bc2 p))) ch)
+//             ||- forever (enterChoice "Choose led to disable" [] [LED1, LED2, LED3]
+//                             >>= \p->sendMsg (fst (makeMsgs 0 (bc3 p))) ch)
+//             ||- viewSharedInformation "channels" [ViewAs lens] ch
+//             ||- viewSharedInformation "messages" [] messageShare
+//             ||- viewSh sdsShares ch
+//             >>* [OnAction ActionFinish (always shutDown)]
+//     where
+//             messageShare :: Shared [String]
+//             messageShare = sharedStore "mTaskMessagesRecv" []
+//
+//             processMessages ch msgs sdss = forever (watch ch
+//                     >>* [OnValue (ifValue (not o isEmpty o fst3) (process ch))])
+//                     where
+//                             process :: (Shared ([MTaskMSGRecv],[MTaskMSGSend],Bool)) ([MTaskMSGRecv],[MTaskMSGSend],Bool) -> Task ()
+//                             process ch (r,_,_) = upd (appFst3 (const [])) ch >>| process` r
+//                                     where
+//                                             process` = foldr (\r t->updateSDSs sdss msgs r >>| t) (return ())
+//
+//             makeMsgs :: Int (Main (ByteCode () Stmt)) -> ([MTaskMSGSend], [(Int, Shared Int)])
+//             makeMsgs timeout bc
+//             # (msgs, st) = toMessages timeout (toRealByteCode (unMain bc))
+//             = (msgs, map f st.sdss)
+//                     where 
+//                             f (i,d) = (i, sharedStore ("mTaskSDS-" +++ toString i) (dd d))
+//                             dd [x,y] = toInt x*265 + toInt y
+//
+//             updateSDSs :: [(Int, Shared Int)] (Shared [String]) MTaskMSGRecv -> Task ()
+//             updateSDSs [(id, sh):xs] m n=:(MTPub i d)
+//             | id == i = set ((toInt d.[0])*265 + toInt d.[1]) sh @! ()
+//             = updateSDSs xs m n
+//             updateSDSs _ m mtm = case mtm of
+//                     MTMessage s = upd (\l->take 5 [s:l]) m @! ()
+//                     mta=:(MTTaskAck _) = upd (\l->take 5 [toString mta:l]) m @! ()
+//                     //TODO other recv msgs
+//                     _ = return ()
+//
+//             lens :: ([MTaskMSGRecv], [MTaskMSGSend],Bool) -> ([String], [String])
+//             lens (r,s,_) = (map toString r, map toString s)
+//
+//             viewSh :: [(Int, Shared Int)] (Shared ([MTaskMSGRecv],[MTaskMSGSend],Bool)) -> Task ()
+//             viewSh [] ch = return ()
+//             viewSh [(i, sh):xs] ch
+//             # sharename = "SDS-" +++ toString i
+//             = (
+//                             viewSharedInformation ("SDS-" +++ toString i) [] sh ||-
+//                             forever (
+//                                     enterInformation sharename []
+//                                     >>* [OnAction ActionOk 
+//                                                     (ifValue (\j->j>=1 && j <= 3) 
+//                                                     (\c->set c sh
+//                                                             >>= \_->sendMsg (toSDSUpdate i c) ch
+//                                                             @! ()
+//                                                     )
+//                                             )]
+//                             )
+//                     ) ||- viewSh xs ch
 
 sendMsg :: [MTaskMSGSend] (Shared ([MTaskMSGRecv],[MTaskMSGSend],Bool)) -> Task ()
 sendMsg m ch = upd (\(r,s,ss)->(r,s ++ m,True)) ch @! ()
 
 sendMsg :: [MTaskMSGSend] (Shared ([MTaskMSGRecv],[MTaskMSGSend],Bool)) -> Task ()
 sendMsg m ch = upd (\(r,s,ss)->(r,s ++ m,True)) ch @! ()
@@ -201,7 +331,6 @@ syncNetworkChannel server port channel
                whileConnected :: (Maybe String) String ([MTaskMSGRecv], [MTaskMSGSend],Bool) -> (MaybeErrorString String, Maybe ([MTaskMSGRecv],[MTaskMSGSend],Bool), [String], Bool)
                whileConnected Nothing acc (msgs,send,sendStopped)
                = (Ok acc, Nothing, [], False)
                whileConnected :: (Maybe String) String ([MTaskMSGRecv], [MTaskMSGSend],Bool) -> (MaybeErrorString String, Maybe ([MTaskMSGRecv],[MTaskMSGSend],Bool), [String], Bool)
                whileConnected Nothing acc (msgs,send,sendStopped)
                = (Ok acc, Nothing, [], False)
-//             = (Ok acc, Just (msgs,[],sendStopped), map encode send, False)
 
                whileConnected (Just newData) acc (msgs,send,sendStopped)
                | sendStopped = (Ok acc, Just (msgs ++ [decode newData],[],False), map encode send, False)
 
                whileConnected (Just newData) acc (msgs,send,sendStopped)
                | sendStopped = (Ok acc, Just (msgs ++ [decode newData],[],False), map encode send, False)