<?php
/*
    Library for sending POCSAG messages via pi-star.
    Remote commands must be enabled for this to work.
    To configure, set the correct values for the constants below.
    This library requires the php ssh2 module to be enabled.
    
    Copyright (c) 2024 HB9HZK.
    
    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and  associated  documentation  files  (the  "Software"),  to deal  in  the  Software without
    restriction,  including without limitation the rights to use,  copy,  modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT  NOT  LIMITED  TO THE  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF  OR  IN  CONNECTION WITH THE SOFTWARE  OR  THE USE  OR  OTHER DEALINGS IN THE SOFTWARE.
*/

//IP address or hostname of the pi-star device
//This is usually shown on the display of the pi-star if when it's connected to a wifi network
define('PISTAR_ADDR','2001:db8:4159:5241::f258');
//SSH Username
define('PISTAR_USER','pi-star');
//SSH Password
define('PISTAR_PASS','raspberry');
//SSH Public key hash. pistar_pocsagSend will write the correct key to stdout if it doesn't matches.
//Delete this line if you don't care about verifying the remote host key
define('PISTAR_HOSTID','0123456789ABCDEF0123456789ABCDEF01234567');
//Time zone the pi-star device is in. Used by pistar_pocsagTime.
//You can delete this line if you want to use the timezone PHP has been configured with
define('PISTAR_TZ','Europe/Zurich');

// == No changes below == //

function pistar_pocsagSend($ric,$message){
    
//Ensure RIC is valid
    
if(!is_numeric($ric) || $ric<|| $ric>2097151){
        return 
FALSE;
    }
    
//Message length is at most 80 characters, and must be ASCII
    
if(strlen($message)>80 || !mb_check_encoding($message,'ASCII')){
        return 
FALSE;
    }
    
    
$message=escapeshellarg($message);
    
$conn=ssh2_connect(PISTAR_ADDR);
    if(
$conn){
        if(
defined('PISTAR_HOSTID')){
            
$key=ssh2_fingerprint($connSSH2_FINGERPRINT_SHA1|SSH2_FINGERPRINT_HEX);
            if(
$key!==PISTAR_HOSTID){
                echo 
'Expected host key id: ' PISTAR_HOSTID PHP_EOL;
                echo 
"Actual host key id:   $keyPHP_EOL;
                echo 
'Please set PISTAR_HOSTID accordingly' PHP_EOL;
                
ssh2_disconnect($conn);
                return 
FALSE;
            }
        }
        
$auth=ssh2_auth_password($conn,PISTAR_USER,PISTAR_PASS);
        if(!
$auth){
            echo 
'SSH authentication failure' PHP_EOL;
            
ssh2_disconnect($conn);
            return 
FALSE;
        }
        
$cmd=ssh2_exec($conn,"RemoteCommand 7642 page $ric $message");
        echo 
stream_get_contents($cmd) . PHP_EOL;
        
fclose($cmd);
        
ssh2_disconnect($conn);
        return 
TRUE;
    }
    else{
        echo 
'Connection failed' PHP_EOL;
        return 
FALSE;
    }
}

function 
pistar_pocsagTime($time=NULL){
    if(
$time===NULL){
        
$time=time();
    }
    else if(!
is_float($time) && !is_int($time)){
        return 
FALSE;
    }
    
$tz=defined('PISTAR_TZ');
    if(
$tz){
        
$tz=date_default_timezone_get();
        
date_default_timezone_set(PISTAR_TZ);
    }
    
$dt=date('ymdHis',$time);
    if(
$tz!==FALSE){
        
date_default_timezone_set($tz);
    }
    return 
pistar_pocsagSend('224',"YYYYMMDDHHMMSS$dt");
}

function 
pistar_Cli(){
    while(
TRUE){
        echo 
'[1] Send time signal' PHP_EOL '[2] Send message' PHP_EOL '[Q] Quit' PHP_EOL;
        
$menu=readline('[1/2/Q]: ');
        if(
$menu===FALSE){
            return;
        }
        switch(
strtoupper($menu)){
            case 
'1':
                echo 
pistar_pocsagTime()?'OK':'ERR';
                echo 
PHP_EOL;
                break;
            case 
'2':
                
$ric=readline('RIC: ');
                
$msg=readline('MSG: ');
                if(
$ric===FALSE || $msg===FALSE){
                    die();
                }
                echo 
pistar_pocsagSend($ric,$msg)?'OK':'ERR';
                echo 
PHP_EOL;
                break;
            case 
'Q':
                return;
        }
    }
}

//Running on command line
if(PHP_SAPI==='cli'){
    
pistar_Cli();
}
else{
//pistar_pocsagTime();
//pistar_pocsagSend('2097151','Call 5555-0123');
}