News:

Precision Simulator update 10.173 (24 February 2024) is now available.
Navburo update 13 (23 November 2022) is now available.
NG FMC and More is released.

Main Menu

Pushover App- integration with PSX PRINT function?

Started by cavaricooper, Fri, 17 Jan 2020 22:51

cavaricooper

I have been using and greatly appreciating the Pushover App (https://pushover.net) during my other sim sessions.  I have come to rely on this App for all my ACARS printing- incredibly simple and handy reference- and no paper waste.

Have one of our Big Sim builders written an implementation for this?  It is simply brilliant and would go hand in hand with PSX superbly.

Fingers X'ed!

Ta- C
Carl Avari-Cooper, KTPA

Jeroen Hoppenbrouwers

Sending the text can be done in 9 lines of Python... no need for any "big" coding here.

import http.client, urllib
conn = http.client.HTTPSConnection("api.pushover.net:443")
conn.request("POST", "/1/messages.json",
  urllib.parse.urlencode({
    "token": "APP_TOKEN",
    "user": "USER_KEY",
    "message": "hello world",
  }), { "Content-type": "application/x-www-form-urlencoded" })
conn.getresponse()


Basically you fill in your APP_TOKEN and that's it.

Getting the ACARS text from PSX is another 10-20 lines.

If nobody else does it, I may shoot at it tomorrow.

Hoppie

cavaricooper

#2
THAT WOULD BE GREAT HOPPIE... it's a brilliant solution! I have made tokens for vPilot and FSL and they both work wonderfully.

Ta- C

PS- is Java possible so it is PSX universal?  Can any PRINT push send the message to Pushover?
Carl Avari-Cooper, KTPA


Jeroen Hoppenbrouwers

... first beta has been submitted to the testing department ...

With certain maximums per application, this would not be a good target to build natively into PSX although it would be a very limited amount of work. Hardy would need to set up the Pushover server with subscriptions and such and although it could even be a (small) source of income for him, my gut feeling tells me that he isn't going to be very interested in this kind of work.   :-)

Now I have a "print to Pushover" implemented, is there any other print redirect that is useful? Like, stupidly dumping the ACARS text out of whatever printer is attached to the PC?


Hoppie

Ton van Bochove

Ton

RogerH

I have a small receipt printer, got for a tenner off eBay, which AdaptPSX sends my prints to quite happily! Sadly, I staple to get her and keep all my printouts along with flying got plans etc.

cavaricooper

#7
Gents-

I appreciate the thoughts, and I too have a Star Receipt Printer.  This program however, obviates that need, saves a few trees and in the process allows for all the notifications you want (ok 7000 per month) with the ability to review on any iOS or Android device of your choosing. 

Then when you like, you can flush and start over.  I for one am very thankful Hoppie took on this task.  It is working brilliantly in Win 10 and I am told it will be multi platform capable when released, as it is written in Python.

I have been bitten and am already addicted :)

Best- C (AKA: the testing department) ;)


PS- the simplicity of having a readily referable "printout" at your fingertips on your iPhone and iPad is truly brilliant!

Carl Avari-Cooper, KTPA

Martin Baker

This sounds fantastic! If you need another pair of eyes to check it out, I'm very happy to oblige :-)

RogerH


Jeroen Hoppenbrouwers

For the fearless:

* Get a Pushover app (there is one just in your webbrowser, no install required): https://pushover.net/clients
* Get a free one-week User Key. After one week it will be a one-time $5 payment (I get nothing of that): https://pushover.net/signup
* Fetch this: https://www.hoppie.nl/tmp/psx-acars-pushover-0.0-beta-1.exe
* In a cmd window, run it with your User Key appended as a parameter. Like so:


c:\path\where\you\put\it> psx-acars-pushover-0.0-beta-1 5g7f845i4586fdfGJ78ykhj97687


* No docs.
* You're on your own.
* Radar service terminated.   :-)


Hoppie

Martin Baker


kwieser76

Product Owner Lido/Flight ASC
Lufthansa Systems (LIDO)

Jeroen Hoppenbrouwers

Sources available. You need Python 3.8 installed on your machine, and maybe a module or two, but I think all modules I used are provided with the base install.

You also need both a Pushover App Key and a Pushover User Key. Both can be gotten from the Pushover web site. You need to buy a $5 Pushover app, which allows you to get a User Key. And if you push more than 7500 messages per month, you need to pay for the App Key.

Source:
https://www.hoppie.nl/tmp/psx-print-pushover.py


Hoppie



# psx-print-pushover.py: simple connector between a PSX Main Server and the
# Pushover server on the internet.


##### Modules ############################################################

VERSION = "0.0-beta-1*"

import asyncio
import argparse
import sys

# For Pushover.
import http.client, urllib


##### Coroutines, Classes, and Functions #################################

async def connect_to_psx():
  """ Keep trying forever to open a connection and run it. """

  while True:
    await asyncio.sleep(2)
    print(f"Attempting to connect to PSX Main Server at {PSXHOST}...")
    try:
      reader, writer = await asyncio.open_connection(PSXHOST, PSXPORT)
    except OSError:
      print("Oops, that failed. Has the PSX Main Server been started?")
      print("Will retry in 10 seconds")
      await asyncio.sleep(10)
      continue

    # We got a connection. Respond to incoming data.
    try:
      while True:
        line = await reader.readline()
        if not line:
          # Waah? Ftuk!
          break
        # decode() converts bytes object to Unicode string object.
        parseLine(line.decode().strip())
      # while the connection is okay
    except ConnectionResetError:
      print("Lost connection to PSX Main Server\n")
    finally:
      # TODO this finally: clause is required; if the code is moved outside
      # the try:-except:-finally: construction, the exception is not caught
      # and we get the dreaded "Event loop is closed" exception.
      # Disconnect cleanly from PSX. encode() produces bytes from a UTF-8.
      writer.write("exit\n".encode())
      writer.close()
      await writer.wait_closed()
# connect_to_psx


def parseLine(line):
  """ Parse an output line from PSX. """
  key, sep, value = line.partition("=")
  # Filter only for relevant keys; drop the rest onto the floor.
  # Triggered actions need to be registered with the Db class, not here.

  if key in [
    "id", "version",
    "Qs119" ]:
    Db.set(key, value)
# parseLine


class Db:
  """ One single Database class, no instances, only class vars/methods. """
  variables = dict()    # (key, value)
  callbacks = dict()    # (key, [callback, callback, ...]

  def set(key, value):
    """ Set the new key to the given value and call the subscribers. """
    Db.variables[key] = value
    # See whether there are any callbacks registered on this key.
    if key in Db.callbacks:
      for callback in Db.callbacks[key]:
        # Call all subscribers with the key and new value as parameters.
        # The key is very useful for multi-key-handling callbacks.
        callback(key, value)

  def get(key):
    """ Retrieve the value stored on the given key. """
    if key in Db.variables:
      return Db.variables[key]
    else:
      print(f"Get {key} which is unknown; trying to return empty string")
      return ""

  def subscribe(key, cb):
    """ Add the given function to the key's callback list. """
    if key in Db.callbacks:
      Db.callbacks[key].append(cb)
    else:
      Db.callbacks[key] = [cb]    # Remember to create a list.
# Db


async def main():
  """ Main Async Event Loop.
      Start the concurrent coroutines and wait forever, until either they
      all end (should not happen) or any unhandled exception breaks out of
      its coroutine.
  """
  await asyncio.gather(
    connect_to_psx()
  )
# main


def processPrinter(key, value):
  if value!="":
    # Replace some PSX-encoded values.
    text = value.replace("^","\n")
    print("\n-----------------------")
    print(text)
    print("-----------------------")
    pushover(text)


def pushover(text):
  """Very basic Pushover client implementation.
 
  This is synchronous, so if the internet hiccups, something will likely
  break. This is where more development is required."""

  # TODO Replace this by for example aiohttp.
  conn = http.client.HTTPSConnection("api.pushover.net:443")
  conn.request("POST", "/1/messages.json",
    urllib.parse.urlencode({
      "token": APPKEY,
      "user": USERKEY,
      "message": text,
    }), { "Content-type": "application/x-www-form-urlencoded" })
  response = conn.getresponse()
  if response.status==200:
    print("Pushover OK")
  else:
    print("Pushover failed: {}".format(response.reason))
# pushover


##### MAIN ###############################################################

print("PSX Python Connector v{}, (C) Hoppie 2020\n".format(VERSION))

p = argparse.ArgumentParser(description="""
       Connects to a PSX Main Server and picks up all virtual printout;
       then sends this printout to a Pushover account so you can get it
       on any device you like (and paid for).""")
p.add_argument("--userkey", help="your Pushover User Key", required=True)
p.add_argument("--appkey", help="your Pushover App Key", required=True)
p.add_argument("--host", help="the PSX Main Server host, "
                              "default 127.0.0.1",
               default="127.0.0.1")
p.add_argument("--port", help="the PSX Main Server port, default 10747",
               default=10747)
args = p.parse_args()
USERKEY = args.userkey
APPKEY  = args.appkey
PSXHOST = args.host
PSXPORT = args.port

# Register all PSX database callbacks.
Db.subscribe("version", lambda key, value:
  print(f"Connected to PSX {value} as client #{Db.get('id')}"))
Db.subscribe("Qs119", processPrinter)

# There can be at most one entry point to the Python asyncio Event Loop.
# When this one returns, the event loop has been "broken" by an unhandled
# exception, which usually means the whole program should be terminated.
try:
  asyncio.run(main())
except KeyboardInterrupt:
  """This only works properly from Python 3.8 onwards."""
  print("\nStopped by keyboard interrupt (Ctrl-C)")

# EOF

kwieser76

HI,

can you tell me where i have to add my user and app key in this code...

thx
Product Owner Lido/Flight ASC
Lufthansa Systems (LIDO)

Martin Baker

Quote from: kwieser76 on Fri, 14 Feb 2020 10:29
HI,

can you tell me where i have to add my user and app key in this code...

thx

If this possible, it would be very useful in order to avoid having to manually enter the key on every start. M

cavaricooper

At the moment it is in very basic form, with the code and PC functionality.  As it is written in Python, it ought to be multi-platform capable, however, at the moment I cannot get it to run on my Mac (OS 10.14.6).  Hoppie has posted the basic code here (for which I am very grateful), so if there is someone with sufficient enthusiasm AND programming ability who cares to take this to the next level and format it into a tidy custom installer, no one would be happier than I.

I can tell you from my experiences with FSL aircraft, it is simply brilliant to be able to have the PRINT function send a ready reference to my iPhone/iPads, without bothering with the HW printer.  The FSL products have a "module" written for them, where one simply puts in their individual Pushover ID and APP KEY once.

Hopefully, that is the next step for PSX also.  Using your own key and app ID, results in your own message limitations and costs, and therefore eliminates any need for Hardy/Hoppie to foot the bill.  At the moment the one time $5 purchase gets you 7500 messages a month.  That has been more than adequate for me.

Fingers x'ed one of our ecosystem developers will run with this.

https://pushover.net

https://forums.flightsimlabs.com/index.php?/files/file/1684-vpilot-pushover-and-hoppie-notifications/

https://forums.flightsimlabs.com/index.php?/files/file/1673-fslabs-mcdu-push-notifications/

Best- C
Carl Avari-Cooper, KTPA

Jeroen Hoppenbrouwers

The program itself is pretty stupid and in its current form cannot do it, but you can craft a Windows .bat file that holds the complete incantation to start it. Clicking that .bat file then will execute the whole rataplan.

Alternatively, a good moment to teach yourself Python  :-)

If people are interested I can show how, instead of just providing the changes.


Hoppie

kwieser76

Quote from: Jeroen Hoppenbrouwers on Fri, 14 Feb 2020 23:50
The program itself is pretty stupid and in its current form cannot do it, but you can craft a Windows .bat file that holds the complete incantation to start it. Clicking that .bat file then will execute the whole rataplan.

Alternatively, a good moment to teach yourself Python  :-)

If people are interested I can show how, instead of just providing the changes.


Hoppie

HI,
I'm interested how i can do that with Python...
As i saw in the code  there is a reference to both key... but i don't how i should do that.

Thx

Kurt
Product Owner Lido/Flight ASC
Lufthansa Systems (LIDO)

Jeroen Hoppenbrouwers

#19
Ok, I'll write a brief Python introduction  :-)

You will need two things to write or modify Python programs yourself:

1. A simple text editor. Notepad is ok but bare-bones. There are many free others that help you better, such as Notepad++. I personally use Vim... yes... I am old. On Windows you probably want gvim.

https://notepad-plus-plus.org/
https://www.vim.org/

Do not get scared by the plethora of features of modern text editors. You need 1% of them, if at all. Again, Notepad will do the job.

2. Python. Just the standard (also free) install is fine. Allow the thing to add itself to the "path" so that you can open a cmd prompt anywhere (in any folder) and the system can still find the "python" command.

https://www.python.org/

To check whether your Python has been correctly installed, open a cmd window and type:


C:\Users\Hoppie>python --version
Python 3.8.1


You need 3.8 at least.

I assume you know what I mean with "cmd" and "type X" with some things your computer generates and some things you type yourself mixed up. If not, we'll cover that, just ask.

Now write your first Python program. Create a flat text file called "mytest.py" and put this in it:


# mytest.py is my first Python program.
print("Congratulations!")


The first line is just a comment. I like comments. They help me remembering what the heck I was doing again.

The second line, well, prints a word onto the screen.

Save the file and see whether it works:


C:\Users\Hoppie>python mytest.py
Congratulations!


If so, congratulations, as the rest should now work, too.

The program file we'll work on is psx-print-pushover.py, as posted above in this Forum thread. Copy it somewhere and make sure you have a backup copy at hand, just in case.

Open the file in your text editor. It is possible that double-clicking does not open it in the editor, but executes it. Personally I want .py files to open in the editor so I kicked Windows to take this default action. Near the bottom of it, you find the "Main" section. This is where things happen. Everything before is just setup for use later on.

I used a pre-written routine that comes with Python out of the box, to read and process the command line parameters such as --userkey. This means that you should modify only this block of text to get what you want: default user and app keys, so you don't need to type them in again and again. The ArgumentParser building block can do this. If you want to read up on it, go to the wonderful Python documentation:

https://docs.python.org/3/library/argparse.html

Exploring this web site is what will keep you busy for as many hours as PSX!  :-)

Here's the unchanged code we're talking about:


p = argparse.ArgumentParser(description="""
       Connects to a PSX Main Server and picks up all virtual printout;
       then sends this printout to a Pushover account so you can get it
       on any device you like (and paid for).""")
p.add_argument("--userkey", help="your Pushover User Key", required=True)
p.add_argument("--appkey", help="your Pushover App Key", required=True)
p.add_argument("--host", help="the PSX Main Server host, "
                              "default 127.0.0.1",
               default="127.0.0.1")
p.add_argument("--port", help="the PSX Main Server port, default 10747",
               default=10747)


You already see several lines that have default values. They may look like duplications, but look closer. The line stating:


"default 127.0.0.1"


is text meant for the user, displayed when (s)he types --help. And the other line,


default="127.0.0.1"


is text meant for the Python program interpreter, to instruct it to set up "127.0.0.1" as the default "host" to find the PSX Main Server on. Both lines convey the same thing, but to different audiences. Try it:


C:\Users\Hoppie>python psx-print-pushover.py --help
PSX Python Connector v0.0-beta-1*, (C) Hoppie 2020

usage: psx-print-pushover.py [-h] --userkey USERKEY --appkey APPKEY
                             [--host HOST] [--port PORT]

Connects to a PSX Main Server and picks up all virtual printout; then sends
this printout to a Pushover account so you can get it on any device you like
(and paid for).

optional arguments:
  -h, --help         show this help message and exit
  --userkey USERKEY  your Pushover User Key
  --appkey APPKEY    your Pushover App Key
  --host HOST        the PSX Main Server host, default 127.0.0.1
  --port PORT        the PSX Main Server port, default 10747


Note that the --userkey and --appkey lines do not have a default! Hey, this is what we're going to add.

Change the code to look like:


p.add_argument("--userkey", help="your Pushover User Key, default is mine",
               default="YOUR_USER_KEY_HERE")
p.add_argument("--appkey", help="your Pushover App Key, default is mine",
               default="YOUR_APP_KEY_HERE")


Save the file, and test the help function again:


C:\Users\Hoppie>python psx-print-pushover.py --help
... stuff ...
optional arguments:
  -h, --help         show this help message and exit
  --userkey USERKEY  your Pushover User Key, default is mine
  --appkey APPKEY    your Pushover App Key, default is mine
  --host HOST        the PSX Main Server host, default 127.0.0.1
  --port PORT        the PSX Main Server port, default 10747


And then run the thing plain, which shall use your own user key and app key without further assistance.

If everything is OK, update the line saying VERSION (at the top) to say whatever you like, update other things, and have fun!

Let me know whether you need any more help. I'll gladly provide it.


Hoppie