ToppyBiff is a concept for a new style of Topfield TAP.
Imagine your Toppy alerting you to new information from the internet:
... or any other timestamped small snippet of read-only information which you might want to be alerted to by a discreet icon on your television screen, upon which you can click to see the information (and have it disappear after you have read it).
Along the bottom edge of your TV screen (or top edge, a configurable option), there would be a row of icons each of which would contain an optional text string or number (e.g. to indicate the number of unread messages) - the icon would represent the type of information being presented: email, stocks, news, syslog, etc.
A single click on the enter key on the remote would put you in selection mode and highlight the first icon, another enter would put you in reading mode and present the first unread message associated with that selected icon, and yet another enter would present the next unread message of that type. If no more were unread, that icon would disappear, and the next icon would be highlighted, ready for reading by hitting the enter key. You would be able to move the highlight on a row of icons to the left and right using the arrow keys whilst in the selection mode. Exit would exit the selection mode.
Information would be uploaded to the ToppyBiff TAP via the well-known TGD format to a specific filename known by the TAP. All messages would be contained in the one single file. The file would be completely overwritten on each upload. Messages have (at a minimum) a date and timestamp, a message type, a subject, and a message body.
The TAP would maintain a separate file containing the date and timestamp, message type and subject of recent messages which have been read. This excludes the need to have a reverse flow of information from the toppy back to the source computer. If an entry in the "read messages" file is dated earlier than the earliest message in the latest upload file, then it can be removed. If an entry in the "read messages" file corresponds to an entry in the latest upload file, then the entry in the upload file is identified as "read" by the TAP. If an entry in the latest upload file does not correspond to any entry in the "read messages" file, then the entry in the upload file is identified as "unread" by the TAP.
Here is the mapping of TGD file formats to ToppyBiff fields:
service_name: Message type
Two threads discussing the older beta versions of EPG_uploader3 that supports some of this functionality:
Release 3.3 and above of the EPG_uploader TAP work best for Toppybiff, with improved reader and different volume levels for the notification supported, download it here: http://tonyspage.abock.de
Some images from Toppybiff: Email icon that pops up when a pending message/messages are there to read:
The list shown when the OK is hit:
The first page of a message when OK is hit:
The second page of a message when OK is hit:
A thread that discusses how these were created here: http://www.topfield-australia.com.au/frm/topic.asp?TOPIC_ID=5166
The images above demonstrate running Outlook an outlook script to display Toppybiff messages on the Toppy. Create VisualBasic? script in Outlook by simply Alt-F11 while in Outlook and paste the following (thanks Adam_G for the code):
' These scripts were written to take advantage of ToppyBIFF '(http://www.nslu2-linux.org/wiki/Puppy/ToppyBiff) ' ToppyBiff allows your TV (if it is using a Topfield personal Video Recorder) ' to display a notification on the screen of receiving an email. You can then ' view the email text on your TV ' ' When a new email arrives the first script formats the message and creates a 99999997.tgd ' message file ' When a reminder occurs the second script creates a message file ' ' These scripts use TFCopy (http://www.8ung.at/aldarin/tools.html) to transfer ' the message file to the Topfield. ' ' ' To use the scripts download TFCopy and modify the Const statement below to point ' to the location of TFCopy.exe ' ' Roger Morton has modified the scripts to use FTP to transfer the files. ' This is useful if you run the FTP server for topfield application (as you do if running ' toppy web [a web interface to the Topfield PVR] ' To use the FTP modify the serverName,UserName and Password vars in the FTPFileToToppy ' Sub to be the appropriate values for the FTP server for Topfield of your setup. ' The code uses PASSIVE mode in the FTP process because RLM needed this. ' I discovered I needed passive mode when WS_FTP complained about "Blocking call cancelled" ' The weird thing is that I only get the "Blocking call cancelled" sometimes. ' But when I do setting FTP to passive mode seems to fix it. ' see http://www.ftpplanet.com/ftpresources/ftp_faq.html ' If you don't want to use Passive mode then in the FTPFileToToppy() function ' replace INTERNET_FLAG_PASSIVE in the ' InternetConnect() call with 0 [zero] ' ' To use this code: ' Open Outlook and press <ALT>F11 to open the Visual Basic editor, navigate to the ' ThisOutlookSession and past this entire code ' ' You will need EPGuploader (http://tonyspage.abock.de/) version 3 BETA or ' later for ToppyBIFF support ' ' Thanks to Tony (http://tonyspage.abock.de/) for writing and maintaining EPGuploader which at the time of this writing is the ' only Topfield TAP with ToppyBIFF support. ' Thanks also to Gary (Jammer) for his help with testing and enhancing these scripts. ' ' Adam_G April 30th 2006 ' ' Topfield Australia forums - http://www.topfield-australia.com.au/frm/default.asp ' ' ' Option Explicit ' ' InternetOpen Initializes an application's use of the WinINet functions. Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _ (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, _ ByVal sProxyBypass As String, ByVal lFlags As Long) As Long ' Connect to the network Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" _ (ByVal hInternetSession As Long, ByVal sServerName As String, _ ByVal nServerPort As Integer, ByVal sUsername As String, _ ByVal sPassword As String, ByVal lService As Long, _ ByVal lFlags As Long, ByVal lContext As Long) As Long ' Get a file using FTP Private Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" _ (ByVal hFtpSession As Long, ByVal lpszRemoteFile As String, _ ByVal lpszNewFile As String, ByVal fFailIfExists As Boolean, _ ByVal dwFlagsAndAttributes As Long, ByVal dwFlags As Long, _ ByVal dwContext As Long) As Boolean ' dwFlagsAndAttributes is File attributes for the new file. ' This parameter can be any combination of the FILE_ATTRIBUTE_* flags used by the CreateFile function. ' dwContext is a pointer to a variable that contains the application-defined value that associates this search ' with any application data. This is used only if the application has already called InternetSetStatusCallback ' to set up a status callback function. ' good site for constants and other API references ' http://www.earlsoft.co.uk/api/ Const FILE_ATTRIBUTE_READONLY As Long = 1 '10x1 Const FILE_ATTRIBUTE_HIDDEN As Long = 2 ' 20x2 Const FILE_ATTRIBUTE_SYSTEM As Long = 4 ' 40x4 Const FILE_ATTRIBUTE_ARCHIVE As Long = 32 ' 320x20 Const FILE_ATTRIBUTE_NORMAL As Long = 128 '1280x80 Const FILE_ATTRIBUTE_TEMPORARY As Long = 256 '2560x100 Const INTERNET_FLAG_PASSIVE As Long = &H8000000 Const INTERNET_SERVICE_FTP As Long = 1 Const INTERNET_DEFAULT_FTP_PORT As Long = 21 ' ' Send a file using FTP Private Declare Function FtpPutFile Lib "wininet.dll" Alias "FtpPutFileA" _ (ByVal hFtpSession As Long, ByVal lpszLocalFile As String, _ ByVal lpszRemoteFile As String, ByVal dwFlags As Long, _ ByVal dwContext As Long) As Boolean ' Close the Internet object Private Declare Function InternetCloseHandle Lib "wininet.dll" _ (ByVal hInet As Long) As Integer Const MessageFile As String = "C:\temp\99999997.tgd" ' This can be any locally accessible location, the file name must remain as 99999997.tgd Const TFCopyEXEPath As String = "c:\tfcopy\tfcopy.exe" ' This is where you have installed TFCopy Const MessageFileDestinationPath As String = "#:\EPGdata\99999997.tgd" ' This is the location on the Toppy where the tgd file should be copied to Private Sub Application_NewMail() 'On Error Resume Next Dim currentNameSpace As NameSpace Dim currentMAPIFolder As MAPIFolder Dim SecondaryMAPIFolder As MAPIFolder Dim currentMailItem As MailItem Dim newBody As String Dim WAIT As Double, blnFTPResult As Boolean Set currentNameSpace = Application.GetNamespace("MAPI") Set currentMAPIFolder = currentNameSpace.GetDefaultFolder(olFolderInbox) ' Select the default mail delivery folder ' if you want to check another mail boxes then specify a secondary mail box like this ' I have a mail box calle Agbioview underneath the main mail box called "Personal Folders" ' vvvvvvv commment this out if you only want to read the inbox Set SecondaryMAPIFolder = currentNameSpace.Folders("Personal Folders").Folders("Agbioview") If FileExists(MessageFile) Then Kill MessageFile ' Delete the old 99999997.tgd file Open MessageFile For Output Shared As #1 For Each currentMailItem In currentMAPIFolder.Items.Restrict("[UnRead]=True") ' Check each mail item marked as unread newBody = Replace(currentMailItem.Body, Chr(13), "<br>") ' Replace CR with tag newBody = Replace(newBody, Chr(10), "<br>") ' Replace LF with tag newBody = Replace(newBody, Chr(9), " ") ' Replace TAB with spaces Print #1, "Email" & Chr(9) & Format(currentMailItem.ReceivedTime, "yyyy/mm/dd hh:mm") & _ Chr(9) & " " & Chr(9) & currentMailItem.Subject & Chr(9) & currentMailItem.SenderName & _ Chr(9) & newBody & Chr(13) ' Write to the message file Next currentMailItem 'vvvvvvvvvvvvvvvv process un read mail in the secondary mail box ' comment this out if you only want to read the inbox For Each currentMailItem In SecondaryMAPIFolder.Items.Restrict("[UnRead]=True") ' Check each mail item marked as unread newBody = Replace(currentMailItem.Body, Chr(13), "<br>") ' Replace CR with tag newBody = Replace(newBody, Chr(10), "<br>") ' Replace LF with tag newBody = Replace(newBody, Chr(9), " ") ' Replace TAB with spaces Print #1, "Email" & Chr(9) & Format(currentMailItem.ReceivedTime, "yyyy/mm/dd hh:mm") & _ Chr(9) & " " & Chr(9) & currentMailItem.Subject & Chr(9) & currentMailItem.SenderName & _ Chr(9) & newBody & Chr(13) ' Write to the message file Next currentMailItem '^^^^^^^^^^^^^ comment this out if you only want to read the inbox Close #1 ' Copy Messagefile to Toppy ' vvvvvvvvvvvvvvvvvvvvvvv un comment to use TFCopy 'Shell (TFCopyEXEPath & " " & MessageFile & " " & MessageFileDestinationPath) ' Transfer the newly created 99999997.tgd file to the Toppy ' Comment out if you are using TFCopy. ' vvvvvvvvvvvvvvvvvvvv FTP file to toppy blnFTPResult = FTPFileToToppy(MessageFile, MessageFileDestinationPath) If Not blnFTPResult Then Debug.Print "FTP failed" End If '^^^^^^^^^^^^^^^ comment out if using TF copy Set currentMAPIFolder = Nothing Set currentNameSpace = Nothing WAIT = Timer While Timer < WAIT + 3 ' Pause for n seconds to allow TFcopy to do it's thing DoEvents 'do nothing Wend End Sub Private Sub Application_Reminder(ByVal ReminderItem As Object) On Error Resume Next Dim newBody, apptTime, apptImportance As String Dim WAIT As Double, blnFTPResult As Boolean If FileExists(MessageFile) Then Kill MessageFile ' Delete the old 99999997.tgd file apptTime = ReminderItem.Start & " to " & ReminderItem.End ' Create the appointment time string newBody = Replace(ReminderItem.Body, Chr(13), "<br>") ' Replace CR with tag newBody = Replace(newBody, Chr(10), "<br>") ' Replace LF with tag newBody = Replace(newBody, Chr(9), " ") ' Replace TAB with spaces Select Case ReminderItem.Importance ' Change the Importance attribute from a number to a word Case 0 apptImportance = "Low" Case 1 apptImportance = "Normal" Case 2 apptImportance = "High" End Select Open MessageFile For Output Shared As #1 Print #1, "Appointment" & Chr(9) & Format(ReminderItem.Start, "yyyy/mm/dd hh:mm") & Chr(9) & " " & Chr(9) & _ ReminderItem.Subject & Chr(9) & "Importance: " & apptImportance & newBody ' Write the file Close #1 ' Copy Messagefile to Toppy ' vvvvvvvvvvvvvvvvvvvvvvv un comment to use TFCopy 'Shell (TFCopyEXEPath & " " & MessageFile & " " & MessageFileDestinationPath) ' Transfer the newly created 99999997.tgd file to the Toppy ' Comment out if you are using TFCopy. ' vvvvvvvvvvvvvvvvvvvv FTP file to toppy blnFTPResult = FTPFileToToppy(MessageFile, MessageFileDestinationPath) If Not blnFTPResult Then Debug.Print "FTP failed" End If '^^^^^^^^^^^^^^^ comment out if using TF copy WAIT = Timer While Timer < WAIT + 3 DoEvents 'do nothing Wend End Sub Function FileExists(strFile As String) As Boolean Dim lSize As Long On Error Resume Next lSize = -1 lSize = FileLen(strFile) If lSize = 0 Then FileExists = True ElseIf lSize > 0 Then FileExists = True Else FileExists = False End If End Function Public Function FTPFileToToppy(pLocalFile As String, pRemoteFile As String) As Boolean Dim lngINetConn Dim lngINet Dim blnRC As Boolean Dim UserName As String Dim Password As String Dim serverName As String 'Dim hostFile As String, localFile As String Const ASCII_TRANSFER = 1 Const BINARY_TRANSFER = 2 serverName = "192.168.5.4" UserName = "anonymous" Password = "firstname.lastname@example.org" FTPFileToToppy = False blnRC = False lngINet = InternetOpen("MyFTP Control", 1, vbNullString, vbNullString, 0) ' Initializes an application's use of the WinINet functions. If lngINet > 0 Then ' hInternetSession, sServerName, nServerPort, sUsername , sPassword, lService, lFlags ,lContext lngINetConn = InternetConnect(lngINet, serverName, INTERNET_DEFAULT_FTP_PORT, UserName, Password, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0) ' Opens an File Transfer Protocol (FTP) for a given site. 'vvvvvvvvvv comment out the above and uncomment out this vvvvvv if you do not want to use passive FTP mode. ' lngINetConn = InternetConnect(lngINet, serverName, INTERNET_DEFAULT_FTP_PORT, UserName, Password, INTERNET_SERVICE_FTP, 0, 0) If lngINetConn > 0 Then 'hFtpSession, lpszLocalFile ,lpszRemoteFile , dwFlags dwContext blnRC = FtpPutFile(lngINetConn, pLocalFile, pRemoteFile, BINARY_TRANSFER, 0) ' hFtpSession , lpszRemoteFile lpszNewFile fFailIfExists dwFlagsAndAttributes dwContext ' blnRC = FtpGetFile(lngINetConn, hostFile, localFile, False, FILE_ATTRIBUTE_NORMAL, BINARY_TRANSFER, 0)' how to FTP files from the Toppy to the PC - for educational purposes If (blnRC) Then FTPFileToToppy = True Else Debug.Print "ERROR IN FTP OF FILE!!!!" & vbNewLine & Err.LastDllError End If InternetCloseHandle lngINetConn ' close the connection Else Debug.Print "ERROR IN InternetConnect!!!!" & vbNewLine & Err.LastDllError End If InternetCloseHandle lngINet ' close the internet Else Debug.Print "ERROR IN InternetOpen!!!!" & vbNewLine & Err.LastDllError End If End Function
If you run a SLUG, you can change the
' Copy Messagefile to Toppy Shell (TFCopyEXEPath & " " & MessageFile & " " & MessageFileDestinationPath)
Dim whocares As Double ' Copy Messagefile to Toppy whocares = Shell("ftp -A -s:c:\ftpcommand.txt slug", vbHide)
And create a file in c:\ called "ftpcommand.txt" with notepad, and add the lines:
cd EPGdata put c:\99999997.tgd QUIT
To stop Outlook asking about the script accessing your email addresses, run this: http://www.mapilab.com/outlook/security/ and allow the access when the popup happens the first time.
To allow Outlook to run this macro when you restart Outlook, you will also have to either set the security level to low, (tools, macro, security, low in Outlook) or create a personal digital signature for the script.
This is detailed here: