UI Simple Sample

From MiOS
Revision as of 07:18, 27 May 2011 by Henk (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

A sample MiOS UI with source code can be downloaded here: http://download.mios.com/MiosPollLoop.zip

This acts just like a proper MiOS UI would. The file MiosPollLoop.cpp contains the code that does all the work of communicating with the MiOS engine. The class PollLoop is what continuously polls the engine in it's own thread, keeping the connection alive, and updating the list of Device, Scene, Section, Room and Category so your front end can show this to the user.

The user interface (the front end) is basic text only, which you can replace with your own code. This is what's in FrontEnd.cpp. If you use the same class/function names for your own front end, then you might not need to make any changes at all to the MiosPollLoop. Otherwise, just change the places in MiosPollLoop where it calls the m_pFrontEnd to call your front end functions instead.

PlatformSpecific.cpp has a couple functions that you'll need to implement for your specific platform. Again, if you use the same function declarations you won't need to alter the MiosPollLoop.

On a Windows PC, unzip the files into a directory on your computer and run MiosPollLoop.exe.

When you run it, it starts FrontEnd::Run(), which starts the front end. The first thing it does is checks to see if this control device itself already has a unique serial number in the MiOS device database, meaning if it's provisioned. This is optional for a control device. See FrontEnd::CheckProvision(). Next, it checks to see if the user has stored already the connection information for his MiOS engine. If not, it calls FrontEnd::PickEngine() which will ask you for your mios.com username (recommended), or an ip address. Substitute FrontEnd::PickLocalEngine() if you're going to allow local connections only without going through mios.com (see comments in Run). It then gets the list of engines that username can control by calling MiosPollLoop::FetchEngines. If you're going to be connecting remotely, it asks for your password at this time and optionally stores it. Otherwise, it will go ahead and connect locally and ask for the password whenever the local connection fails.

It then starts MiosPollLoop::StartMainLoop(), which creates a new thread and that starts MiosPollLoop::MainLoop(), which is the main polling function that just loops forever until you tell it to quit. StartMainLoop() returns immediately, so the front end can now continue in it's main loop waiting for user interaction. At this point, your front end will see m_pPollLoop->m_State is state_Disconnected, meaning the connection isn't established yet, so the front end should display a grayed out UI and a busy indicator.

As soon as the polling loop makes a connection and fetches data, it will call FrontEnd::NewData(). This is the function where you should iterate through the PollLoop's m_mapDevice, m_mapScene, m_mapSection, m_mapRoom and m_mapCategory and render the complete UI. You can also re-check the m_pPollLoop->m_State when you're rendering and show the engine is being either disconnected (value -2 means the user can't do anything--the state you started out at), busy (value 0,1,5 or 6 means the engine is busy and the user can continue although some commands will fail), error (value 2 or 3 means the user engine is connected and running but there are problems so it may not be fully functional), success (value 4 meaning the engine just finished doing something that went ok), none (value -1 is the 'normal' meaning nothing is going on). If pPollLoop->m_sComments is not empty, then this string has comments that explains to the user what the engine is doing, or why it is in the state it is, such a description of the error. Display this in your UI if it's not empty.

As you render, you need to keep pointers to the devices and scenes you render since they can change on the fly. For example a device may go on or off. You don't want to re-render the whole UI since that could be slow and introduce a flicker. So provide a way to re-render devices and scenes. Don't worry about providing a way to re-render rooms and sections and don't worry about adding or deleting devices since if the rooms/sections change or devices/scenes are added/removed you'll get FrontEnd::NewData() called again to re-render everything. NewData() is not called that often; mainly when the user saves new changes. But it's a good idea to save whatever device or scene the user last selected when you re-render everything with NewData, so that if that device and scene still exists (remember it could be deleted), you can re-select them so the user doesn't lose his place.

Whenever a device or scene has changed and you need to re-render it on the fly, FrontEnd::DeviceChanged or FrontEnd::SceneChanged will be called. If the engine itself changes, for example, if it goes busy, or the connection is dropped, your FrontEnd::StateChanged will be called.

The other functions in FrontEnd that will get called by the PollLoop are ConnectionFailed() whenever you need to let the user know the connection to his MiOS system is lost and can't be recovered, RetryingConnection() if the connection was lost but the PollLoop found an alternative connection to try (such as the IP address changed, or auto switching from local mode to remote mode), PromptForPassword() means the PollLoop was in local mode and is switching to remote but doesn't have a password and is going to block indefinitely until you provide a password (see: FrontEnd::DoPromptForPassword), and PromptForUserPassword() is called if the username/password does not work and you need to re-establish a connection and again the PollLoop will wait for you to clear the m_bBadUserPass flag so it knows to try again.

You can also set the m_bSuspend flag in PollLoop to temporarily suspend the polling until you set it back to false, and you can set m_bQuit to true to make the PollLoop exit. You can monitor the m_bIsRunning flag to know when it has exited.

You should create a mutex as shown in the example since both your front end thread and the PollLoop's background thread will be manipulating the same data at the same time.

Personal tools