Printing in SB programs

Post Reply
Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Printing in SB programs

Post by Henko »

Direct printing in SmartBasic

Summary

SmartBasic ("SB") does not have a facility to print data on a printer. This document describes a method which enables such facilty and contains the software to implement the method.
The method consists of a number of SB functions to reside on an iOS device and a little webserver, written in Python, on a PC with a printer attached to it.
Presently, the method is restricted and tested for use with a Windows PC and a cable attached printer. It should not be too difficult to extent the method to cover using a MAC computer and/or a network printer, by modifying the webserver applet.

Components

The components of the solution are indicated in the sketch hereafter.

IMG_1572.PNG
IMG_1572.PNG (337.93 KiB) Viewed 5726 times

There are two "low-level" components:

- a SB function (named eprt(a$) in the scheme), which accepts a string as parameter and sends this string to the PC via WiFi, using a HTTP command with the IP adress of the PC.
- a webserver applet in the PC, currently written in Python, which fetches the string and sends it to the printer with a Notepad command, using the current font setting of Notepad.

Alternatives (MAC instead of PC, network printer instead of cable attached printer) might be realized by modification of the webserver applet. If such modifications are in fact realized, please add them to this document.

One peculiarity exists regarding the IP adress of the PC. It is hardcoded in the SB function. However, it is an adress which may be dynamically changed by the router.
In the current situation, when printing fails, the local IP adress has to be found using the Windows "ipconfig" program and entered into the SB program
No method has been found yet to automatically ensure that the correct IP adress is used in de SB function.
For now one could put ipconfig on a shortcut on the toolbar so that one can quickly fetch the PC's address.

"High-level" components

Those are SB calling programs that make use of the printing functionality.
As a little example serves a code snippet which prints a SB source listing (of course any piece of text can be printed with it).

A more elaborate example is a function suite to print multipage reports of any kind. Initial preparation consists of testing the number of characters per line and the number of lines per page. These are printer and font specification dependent. Using these numbers, large reports may be printed where the functions keep track of jumps to new pages, adding a report title, date/time stamp, and a page number to the new page, and columns headings if they are specified.

Step by step installation

The steps to implement and test this feature are as follows:

1. Install Python on the PC system (free, website "Python.org" -> "Download"), if not already installed.

2. Create or choose a directory where to run the webserver

3. Copy/paste the webserver code into Notepad and save it in the chosen directory giving it a filename with extension .py, for instance "iOS2print.py".

4. Open the command line window (CMD), switch to the webserver directory ("CD \xxxx") and start the server: "python iOS2print.py". The message "Print Server started..." should appear. It may be simplified by making a .bat file:
"CD \xxxx
Python iOS2print.py",
and create a shortcut for it on the desktop.

5. Make a little testprogram, or use the one herafter.

6. Switch the printer on, wait until it is ready and run the testprogram. The content of the string should be printed now. From the output you can deduct the number of caracters/line and lines/page.

7. The webserver may be stopped with CTRL-C.


Software components

The two basic components are the low-level SB function and the Python webserver applet for the PC:

Code: Select all

def eprt(t$)    '  low-level SB print function
dim h$(3)
h$(1) = "content-type:text/html"
h$(2) = "content-length:"&len(t$)
HTTP "192.168.2.5" HEADER h$ POST t$ ' IP adress of PC
end def
And the webserver applet :

Code: Select all

# Software by Michiel Overtoom, motoom@xs4all.nl
import os
from http.server import BaseHTTPRequestHandler, HTTPServe
class MyPrintService(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers["Content-Length"])
        post_data = self.rfile.read(content_length)
        with open("report.txt", "wb") as f:
            f.write(post_data)
        os.system("notepad /p report.txt")
if __name__ == "__main__":
    print("Print Server started...")
    HTTPServer(("0.0.0.0", 80), MyPrintService).serve_forever()
The next component is an utility that prints a test sheet, which may be used to establish the number op characters/line and the number of lines/page of your printing device. These numbers are necessary for the report function suite to function properly.:

Code: Select all

option base 1
url$="192.168.2.9"   ' the URL of the host PC
dim h$(2)
' construct a string to measure how many caracters per line and
' how many lines fit on one page
'
t$="1234567890"
for i=1 to 80 ! s$&="regel "&i&chr$(13)&chr$(10) ! next i
for i=1 to 10 ! s$&=t$ ! next i
h$(1) = "content-type:text/html"   ' make header info
h$(2) = "content-length:" & len(s$)
HTTP URL$ HEADER H$ POST s$   ' send doc to the webserver
end
The next code snippet may be used to print a listing of an SB progam on paper, oa any text file for that matter. An advantage of this method over other methods is that additional features may be added to the listing. For instance, adding line numbers to the program lines is a peace of cake.

Code: Select all

' print a SB source file (or any text file)
' mind the current IP adress of the PC !
'
do input "filename ?": f$ ! until file_exists(f$)
do
  file f$ readline dt$
  t$ &= dt$ & chr$(10)
  until file_end(f$)
eprt(t$)
end
Finally there is the report function suite.
A report is entirely packed into one string. When the report is finished, the built report string is sent to the PC to be printed on the default printed.

There are 3 functions to accomplish this:

"Iprt" - An initialization function, to be used once for each report, prepares the header strings, starts the report string, and does some initializations for the line printing function.

"Prt" - adds one line to the report string, and insets the header info into the report string when a new page is detected.

"Eprt" - sends the report string (or any other string supplied by the calling code) to the printer.

Proper inserts of the heading info on each page depends on the value of the "lpp" (lines per page) value when invoking the "lprt() function. This value, in turn, depends on the settings of the Windows "Notepad" program, with respect to font and font size. The best way is to use the little testprogram already presented.

In addition to the 3 basic functions, there is a demo (main) program which calls the functions, and there are some utilities to take care of date/time and column aligning.

(Main) Demo program:

Code: Select all

' Demo program, generates a multipage report with rubbish content
' and demonstrates the use of the three print functions to print
' the report on the default printer of a PC system.
' The three function follow the test program, together with some
' auxiliary functions.
'
dim col_head$(3),lin$(100)
rname$="Spare parts in stock at Newport"  ' title of the report
restore to columns
for i=1 to 1 ! read col_head$(i) ! next i  ' column headings
columns:
data " Code   Description  Quantity   Price"
data "  nr      of item    in pieces  $/pc"
restore to lines
for i=0 to 4 ! read lin$(i) ! next i  ' 5 lines with random content
lines:
data "  xxx    fuhvhijfxd       328   20.45"
data " gyyy       fcjkhjk        42   48.00"
data "  sde      d bmiddg      1523    4.99"
data "  sdu       hfc hhj       469    3.50"
data " umkj     fmoputdsn         5  120.40"
l$ = " cccc     ddddddddd       nnn   nn.nn"
for i=5 to 60 ! lin$(i)=l$ ! next i  ' additional lines to exceed
                                     ' the length of one sheet
' initialization of header info, # lines per sheet, and
' # characters per line (used to centre the title, and
' cut off the title in case it is too long
'
iprt(rname$,col_head$,58,70)
'
' generate 60 lines, which is enough to exceed one sheet
'
for i=0 to 60 ! prt(lin$(i)) ! next i
'
' print the report on the screen, if desired
'
print prt.t$
'
' print the report on the printer
'
' eprt(prt.t$)
end
The 3 basic functions:

Code: Select all

' initialization for printing a report
' rname$ = report title, is printed on each page
' col_head$() = 0, 1 or 2 strings with colomn headers
' lpp = # of lines per page
' cpl = # of characters per line
'
def iprt(rname$,col_head$(),lpp,cpl)
ob=option_base() ! option base 1
set output font size int(1250/cpl)
'                 make report header
prt.rn$=date_time$() ! ld=len(prt.rn$) ! av=cpl-ld-8
lr=len(rname$)
if lr>av-4 then ! rname$=left$(rname$,av-4)! lr=av-4 ! end if
sp=(av-lr)/2
prt.rn$&=ft$(sp+lr,rname$)&ft$(sp+5,"page ")
'                make columns headers
prt.header$=""
h1$=col_head$(2-ob) ! lh1=len(h1$)
h2$=col_head$(3-ob) ! lh2=len(h2$)
if lh1 then prt.header$ &= h1$ & lf$()
if lh2 then prt.header$ &= h2$ & lf$()
'                underline the column headers
sp$="" ! ns=min(lh1,lh2)
for i=1 to ns
  if asc(mid$(h1$,i,1))+asc(mid$(h2$,i,1))>64 then sp$&="~" else sp$&=" "
  next i
if lh1>ns then
  for i=ns+1 to lh1
    if mid$(h1$,i,1)>" " then sp$&="~" else sp$&=" "
    next i
  end if
if lh2>ns then
  for i=ns+1 to lh2
    if mid$(h2$,i,1)>" " then sp$&="~" else sp$&=" "
    next i
  end if
prt.header$ &= sp$
'         initialize some more values for the prt() function
prt.hfix=3+sgn(lh1)+sgn(lh2)
prt.lc=lpp+1 ! prt.lmax=lpp ! prt.page=0 ! prt.t$=""
option base ob
end def

def prt(a$)
if lc>=lmax then
  page+=1 ! lc=hfix
  t$ &= rn$ & page & lf$ & lf$ & header$ & lf$
  end if
lc+=1 ! t$ &= a$ & lf$
end def

def eprt(t$)
dim h$(3)
h$(1) = "content-type:text/html"
h$(2) = "content-length:"&len(t$)
HTTP "192.168.2.9" HEADER h$ POST t$  ' IP adress of PC
end def
And the additional utilities:

Code: Select all

def date_time$()
dim m$(13)
restore to months
for i=1 to 12 ! read m$(i) ! next i
months:
data "january","february","march","april","may","june","july"
data "augustus","september","october","november","december"
y=current_year() ! mo=current_month() ! d=current_date()
h=current_hour() ! mi=current_minute()
dt$=m$(mo)&" "&d&","&y&" "&h&"."&mi&"h"
return dt$
end def

' print formatting of numbers
' n is total fieldwith, -n puts %-sign at end of number
' field starts and ends with one space
' number is right justified if smaller than fieldwith
' number is truncated if larger than fieldwidth
'
def fn$(n,x)
sp$="                             "
if n<0 then p=1 else p=0 ! n=abs(n)
v$=x ! lv=len(v$) ! dp=n-lv-p-2
if dp<0 then v$=left$(v$,lv+dp)
ret$=" " ! if dp>0 then ret$&=left$(sp$,dp)
ret$&=v$ ! if p=1 then ret$&="%" ! ret$&=" "
return ret$
end def

' print formatting of texts
'
def ft$(n,v$)
sp$="                             "
lv=len(v$) ! dp=n-lv-2
if dp<0 then v$=left$(v$,lv+dp)
ret$=" " ! if dp>0 then ret$&=left$(sp$,dp)
ret$&=v$&" "
return ret$
end def

def lf$ = chr$(13)&chr$(10)
Finally, some remarks are included from RBytes, who made some first tests with the printing method:

"
I had a couple of printing glitches this morning that I thought I should share. I had a small program for which I wanted a code printout. I sent it to the printserver a couple of times, with no response. Since I had some internet issues earlier today and had rebooted my modem/router, I suspected that my tablet IP address had been dynamically reassigned. I ran ipconfig and discovered that it had. Only the last of the 4 sets of digits had changed slightly, but since they didn't match the setting in my SB program, nothing could print.

I fixed the IP address in my SB code, then printed the program. The font was huge! It took 4 pages to hold all of the text.
I opened Notepad on my PC tablet and checked the font setting. It was Courier, 24 points! I set it to Arial 12, sent the file to the printserver again and now the printing looked great and required just two pages.

I still don't know why my Notepad's font size setting was so large. I did find that if you open Notepad before you print, set your desired font name and point size, then close it, your text will print with that setting. If you leave Notepad open, the print server will not function.
You may prefer to use a monospaced font if you are printing columns, tables, or anything else that requires horizontal alignment. The only standard Windows monospaced fonts are Courier New (has serifs) and Lucida Sans Typewriter (no serifs).
"

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Printing in SB programs

Post by GeorgeMcGinn »

I created a PDF file that contains the entire text of this post and a complete listing of all the code that is in this post.

You can find this PDF file at: https://www.dropbox.com/s/k9qsguqwh7ki8 ... s.pdf?dl=0

I think I created this link so that everybody can view it. If you cannot get to this link, please email me at gjmcginn@iCloud.com.

Just so you know, I was able to create this PDF by first selecting the entire post and pasting it into apple Pages program. It seems that it's when you select the entire post, it does also do a select all on the code, which means you will get every single line of code and not just what's shown.

I felt that this post was very important and that it needed a document that you can print and see every line in it so that you can read it and comprehend it. I did this because for some people this might be complicated and to have something that you can read and mark up and look at the entire source codes that are involved will help you greatly.

Henk and Rbytes did a fantastic job at developing and testing this so that we all could benefit and do something that isn't programmed in smart BASIC and that is print your results or your source code to a printer. I personally thank them for all the hard work in getting this to work. I have also installed it on my iMac and it worked great.

Again thank you for all your hard work In making this a reality.
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Printing in SB programs

Post by Henko »

George, thank you for producing a PDF. I don't have a tool for that.
One question: you made it function on a MAC. Did that require modifications or additions that need to be mentioned in the document? You have broaden the application area.

It would also be nice if someone (you perhaps) is able to check / implement it in combination with a network printer (not for me, but a lot of people who do programming have installed a network printer, i think)
Thanks again

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Printing in SB programs

Post by GeorgeMcGinn »

I'll check, but I don't recall making changes, at least major ones.

The reason is a webserver is a webserver, regardless of the platform it runs on. I spent 25 years running my own webserver for clients and to sell virtual websites, and the webserver runs on top of the OS. Whether it is a Unix, Linux, Apple or Windows OS, most webservers are transparent to the OS.

For example, I've ran Windows 2003 Server on Windows, Apple (G5 Xserve server) and on a Unix machine. Also, many of the original web servers, like FreeBSD, Red Hat, will run on any OS. More specifically, the webserver is designed for each OS so that the user doesn't know what machine it's running on unless they need root access to the server.

So I will check again but I doubt that I made any serious changes. I think the changes I made were more specific to my webserver then to my OS.

Also, I do believe that my printer is a network printer, as well as a Wi-Fi printer. But I will check to make sure that that's the case because my Apple OS and the Mac server OS both have access to the printer and I quite frankly I'm not sure which is allowing it the print. That's a good question, because in this case I am running a server on top of my iMac OS, and it would be interesting to see which it's using to do the printing.



Henko wrote:
Mon Oct 22, 2018 5:03 pm
George, thank you for producing a PDF. I don't have a tool for that.
One question: you made it function on a MAC. Did that require modifications or additions that need to be mentioned in the document? You have broaden the application area.

It would also be nice if someone (you perhaps) is able to check / implement it in combination with a network printer (not for me, but a lot of people who do programming have installed a network printer, i think)
Thanks again
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Printing in SB programs

Post by rbytes »

It would also be nice if someone (you perhaps) is able to check / implement it in combination with a network printer
I can confirm that your technique works perfectly with a network printer.. I have an HP OfficeJet Pro 8610 network inkjet printer sitting in the den. When I run your SB print program on my iPad, the data is sent wirelessly to the Python printserver on my CHUWI Windows 10 tablet, opened in Notepad and then wirelessly sent to the printer. The transmission is almost instant. If I leave the door to the den open I can hear the printer start to work just a second after I send the print job from my iPad. None of the devices is connected with any other using data cables.

The best news is that no modifications were needed to any of the code you supplied. The only thing I would wish is that when I have to reset my modem/router due to video streaming issues, my PC tablet is not assigned a new IP address. I would like to see if I can configure just that one device to always use the same IP address, but I would be concerned if that made my network less responsive to new connections. It only takes a minute to run ipconfig and edit the IP address in the Smart Basic code.
The only thing that gets me down is gravity...

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Printing in SB programs

Post by GeorgeMcGinn »

This is why I didn't need to make very much changes, as I print to a network printer that is a WIFI-only connected.

I have a thermal dye photo only printer, but I haven't yet hooked it up as I am still unpacking my office boxes. That will need to go through the webserver, which can be accessed either by Ethernet or WIFI (I love that about iMacs) and I can even attach my iMac via Bluetooth.

Henk, I haven't forgotten about your request but I've been working more in TechBASIC right at the moment.



rbytes wrote:
Tue Oct 23, 2018 4:49 am
It would also be nice if someone (you perhaps) is able to check / implement it in combination with a network printer
I can confirm that your technique works perfectly with a network printer.. I have an HP OfficeJet Pro 8610 network inkjet printer sitting in the den. When I run your SB print program on my iPad, the data is sent wirelessly to the Python printserver on my CHUWI Windows 10 tablet, opened in Notepad and then wirelessly sent to the printer. The transmission is almost instant. If I leave the door to the den open I can hear the printer start to work just a second after I send the print job from my iPad. None of the devices is connected with any other using data cables.

The best news is that no modifications were needed to any of the code you supplied. The only thing I would wish is that when I have to reset my modem/router due to video streaming issues, my PC tablet is not assigned a new IP address. I would like to see if I can configure just that one device to always use the same IP address, but I would be concerned if that made my network less responsive to new connections. It only takes a minute to run ipconfig and edit the IP address in the Smart Basic code.
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

Post Reply