This post is also available in: Russian
Over the recent years, the largest TV manufacturers are actively exploring into Web-based TV service, and Panasonic is no exception at that. The Japanese company experts have implemented their vision of Smart TV based on the Viera Connect technology.
From the Panasonic’s Press Release:
VIERA Connect? VIERA Connect is Panasonic’s connected TV platform which enables owners of VIERA Connect-enabled HDTVs, Blu-ray Disc Players and Home Theater Systems access to a wide range of content, from news to social networking and online gaming.
In this post, we would like to share our experience in application development for Viera Connect.
Setting up the Development Environment
First of all, we have to set up the development environment. Well, let’s remind ourselves that Panasonic does not provide an emulator for application development. This means that to start developing an application you’ll need a VIERA Connect-enabled Panasonic TV. Also you’ll need a server that to host a back-end application. The host on which you would like to deploy the backend must either have IP address of 192.168.0.100 or domain name localserver.vieraconnect.com. We chose the second option, as it allowed us to make the development process more flexible. On the local machine of one of our developers, we launched the host – localserver.vieraconnect.com and the bind9 DNS server. Next, to the network connection created on our TV, we enter the address of our local DNS.
Hello, World!
Next, we attempt to launch a test application. At that instance, the TV sends a request to localserver.vieraconnect.com/sdkapp/main.js. The documentation says that this is the main file that launches the application. So there we have entered the code of our «Hello, world!» app. Having made it sure that the development environment is configured, we ran test applications of the Panasonic SDK. Studying of the runtime code helped us fill in the gaps left after reading the documentation which is a bit succinct, just listing the language elements with their options, features and brief explanations.
Application Structure
Any Panasonic Viera Connect application consists of stages (or screens). The aforementioned main.js is the main stage, i.e., the entry point into the application. Stages usually contain graphic user interface elements and code to interact with the user. In our case, we have moved away from this concept and used main.js to attach all the necessary libraries to further redirect the user to the application’s main page.
Another important concept is package. It manifests the Panasonic-recommended way to organize your code. The package may include declaration of variables, objects and functions that after connecting the package become visible globally, on any Stage. The code of one package will also be invokable from the others. The package code ends with the provide() instruction making the package available for the application. Packages might be helpful in creating global objects such as navigation, userInput, userAuthentication etc.
Parallel Work of Several Team Members.
The absence of an emulator in the SDK substantially complicates development, as several developers have to share a single TV. Therefore, they have to constantly re-adjust the device to the application version run by a developer. The procedure for changing the DNS server address in the network connection settings takes about 30 seconds, so doing this too often might be too expensive. You can configure the device to the specific server and use a version control system to update the code, but you would need to commit so frequently that the overhead would very quickly exceed reasonable limits. From this situation, our team came out with a not very elegant but still quite easy workaround. We have configured the TV to interoperate with a backend hosted on the computer of one of our team members, shared the project folder on Samba, and other developers mounted it as a remote file system. This way we improved the efficiency of our development, although limited concurrent access to specific files.
Application Development
Navigation System
When developing an application for Panasonic Viera TV, our team has faced lots of interesting issues. One of the most sophisticated issues was to develop the navigation system. It should be noted that large code debugging on Panasonic Viera Connect devices is immensely hampered by the lack of testing tools. We are going to discuss this in more detail a little bit later. In this regard, we first developed a browser-based navigation system prototype. Only having written the main classes constituting the core of the system, we moved development to a real device.
First, we developed three main classes:
- NavigationStage
- NavigationArea
- NavigationNode
NavigationStage contains general methods to move the cursor on the stage and navigate between stages. NavigationArea is a class to define a navigation area combining the NavigationNodes elements. Areas can be neighboured by other areas at the top, bottom, left and right. This is also true for the navigation elements. Navigation elements are virtual, but store a reference to the element on the stage. We can change visual representation of an element depending on whether it is in focus or not.
NavigationArea and NavigationNode interfaces contain similar methods: executeSelect and executeLeave. They are invoked when an area or item gains or loses focus. In addition, NavigationNode objects also have an executeEnter method called for an item in focus when the user clicks OK on the remote.
All navigation areas behave similarly. When initially setting the cursor in the navigation area, a default navigational element is activated for it. If the user moves the cursor to another area, we store the index of the last active navigation element. We need this, so that when the cursor comes back, we are able to activate the item that initiated the transition.
Here is an example. Suppose the user has entered the "Movies" section and chosen "Crime" in the left menu. If the user clicks the right button on the remote, the cursor will move to the first item in the list of movies. Let’s say further a user clicks the left arrow to revert to the list of categories. The cursor moves back to the "Crime" subcategory.
Early in the development cycle, all the navigation elements and areas behaved identically. Originally, these were text labels that changed color depending on the position of the focus and this behavior has been registered in the NavigationNode class. When we designed a movie slider, we faced the need to create more complex navigational elements to contain arbitrary collection of graphics and text. Therefore, to describe behaviour of a navigation element we created a separate strategy-type class to pass its object to the navigation element builder. This approach worked perfectly, but not for long. The fact is, while we were creating navigation areas with identical elements, such as movie grids or sliders, it was all OK. After that, we faced the need to create navigation areas consisting of arbitrary elements. Also, while assigning search functions to the keypad, we needed not just to define behavior strategy for each element, but also to pass additional behavior parameters to it. Here is an example. We have to enable a keypad to enter search queries. The keypad has four types of buttons that assume different behavior strategies:
- CharButtonStrategy
- CursorMoveButtonStrategy
- BackspaceButtonStrategy
- SwitchLayoutButtonStrtegy
Each CharButtonStrategy button receives configuration array which contains the character code that will be added to the search string when you click on this button. SwitchLayoutButtonStrategy accepts an array containing character set ID to be enable, letter case, etc.
Also, we have employed a similar approach to create pop-ups: the "yes" and "no" buttons are assigned different behavioral strategies in the designer. To initialize strategies, strategy-specific parameters are used.
Scrollable Containers
Another major challenge was to implement scrolling interface elements, i.e., scrollers.
When we designed scrollers, we decided to write a library that would convert any element of the container type into a scrollable area, with automatically calculated scroll step. The only assumption we have made was, that in our interface only containers hosting navigation elements are scrollable. An example of such a container is the subcategory menu.
That’s why, we have combined container scrolling events with moving the focus from one navigation element inside the container to another. To access element navigation events, we use the above-mentioned navigation system. While creating a navigation area, we set the relative position of elements in it, then when the focus moves from the first to the second menu item located under it, we always have to calculate how far the scroller has to be moved. This way, the first version of the scroller was implemented. During the development process, it became clear that the scroller should not scroll always. For example, in the above example at moving from the first to the second menu item, scrolling is of no sense as there is still a lot of visible menu items on the screen. So when should we finally enable scrolling? We have decided to scroll the scroller only if the target element is located close to the center of the scroller. Next, we implemented the code to validate that the borders of rectangle surrounding scrollable content are always outside the scroller boundaries.
It is worth noting that all the stage elements are following polar coordinate system with zero coordinates in the center of the screen. This specifics has to be considered at design phase.
Code Debugging
Panasonic does not provide any built-in debugging tools. This means that while debugging your application its host stage would either run or drop altogether, making you to slowly roll your code back to an operable version in order to identify and fix the problem. We may try to somewhat simplify this task. In the developer documentation, Panasonic suggests writing a feature to output debug messages. The bottom line is that with http_request object at runtime, you can send asynchronous requests to your application backend and log them. We saved messages to a file, then opened it using the tail debug.log-f command. It should be noted that with this approach you should not expect that all debug messages will be logged in the sequence they emerge while running the code, as the request is asynchronous. To partially solve the issue, we can concatenate debug messages in one string and then send them to the server in a single request. However, this approach is applicable only if the code from the first debug message through the string sending the entire log to the server is error-free, otherwise the message will fail.
Conclusions
Let’s try to briefly summarize what we have discussed above. Application development for the Viera Connect platform is all but easy. In addition to design and coding, the developer has to solve a multitude of technical issues, i.e., set up the development environment and write the necessary utilities. Debugging of the application is substantially complicated by the absence of an emulator in the SDK and by the specifics of Panasonic devices.