📄 komunikator.cpp
字号:
pTrPoruka->PostaviKomponentu( KP_START , START_PORUKE );
pTrPoruka->PostaviKomponentu( KP_KOMANDA, IDkomande );
pTrPoruka->PostaviKomponentu( KP_SERIJSKI_BROJ,
( KKorisno::Instance()->KonvertIntUBCD( nSerijskiBroj, 4 ) ).cString );
pTrPoruka->PostaviKomponentu( KP_SUMA, 0 );
transakcija.DodajPoruku( *pTrPoruka );
}
// Pomocna procedura : dodaje prijemnu poruku u transakciju
void KKomunikator::DodajPorukuZaOdgovor( unsigned int nDuzinaOdgovora, bool bKodirajSadrzaj,
IDFormataPoruke formatOdgovora ){
KTransankcionaPoruka* pTrPoruka;
pTrPoruka = new KTransankcionaPoruka( KOpisTPoruke( KOMANDA_PRIMI, nDuzinaOdgovora, bKodirajSadrzaj ),
formatOdgovora );
transakcija.DodajPoruku( *pTrPoruka );
}
// Pomocna procedura : u transakciju dodaje poruku sa podacima za slanje terminalu
void KKomunikator::DodajPorukuPodatakaZaTerminal( EIDKomande IDkomande, bool bKodirajSadrzaj,
string cPodaciZaTerminal ){
KTransankcionaPoruka* pTrPoruka = new KTransankcionaPoruka( KOpisTPoruke( KOMANDA_POSALJI, 0, bKodirajSadrzaj ),
FP_PODACI_TERMINAL );
pTrPoruka->PostaviKomponentu( KP_START , START_PORUKE );
pTrPoruka->PostaviKomponentu( KP_KOMANDA, IDkomande );
pTrPoruka->PostaviKomponentu( KP_SADRZAJ, cPodaciZaTerminal );
pTrPoruka->PostaviKomponentu( KP_SUMA, 0 );
transakcija.DodajPoruku( *pTrPoruka );
}
// Pomocna procedura : izvrsava transakciju i izdvaja korisne podatke.
// U slucaju neuspeha vraca false;
bool KKomunikator::ProcitajPodatkeSaTerminala( string& cKorisniPodaci ){
bool izlaz = false;
if ( IzvrsiTransakciju() ) {
cKorisniPodaci.erase();
DajPodatkeIzTransakcije( cKorisniPodaci );
izlaz = true;
}
return izlaz;
}
// Ocitavanje podataka sa terminala, za brojilo sa datim serijskim brojem.
// Ocitane podatke vraca preko parametra cKorisniPodaci. U slucaju neuspeha vraca false.
// Ako je nDuzinaOdg==0, uzima se duzina odgovora definisana u spisku komandi.
bool KKomunikator::OcitajPodatak( EIDKomande ID, unsigned int nSerijskiBroj, string& cKorisniPodaci,
unsigned int nDuzinaOdg ){
bool izlaz = false;
KKomanda komanda;
// Uzima u obzir samo komande iz spiska ( 'podrzane' komande )
if ( KSpisakKomandi::Instance()->DajKomandu( ID, komanda ) ) {
// Inicijalizuj transakciju
ResetujTransakciju( string( "Ocitavanje podatka" ) );
// Formiraj komandu ( poruku formata FP_KOMANDA_TERMINALU ) koja se salje terminalu
DodajKomandnuPoruku( ID, false, nSerijskiBroj );
// Formiraj poruku za odgovor od terminala
if ( nDuzinaOdg == 0 ) {
if ( adminInfo.bDodatniOpisRT ) {
// nova verzija
DodajPorukuZaOdgovor( komanda.nDuzinaOdgovora + 1, false, komanda.formatOdgovora );
}
else {
// stara verzija
DodajPorukuZaOdgovor( komanda.nDuzinaOdgovora, false, komanda.formatOdgovora );
}
}
else {
// Ako je duzina odgovora zadata ( npr za 'admin info' i za 'opis terminala' ),
// ne modifikujem je :
DodajPorukuZaOdgovor( nDuzinaOdg, false, komanda.formatOdgovora );
}
// Izvrsi transakciju
izlaz = ProcitajPodatkeSaTerminala( cKorisniPodaci );
}
return izlaz;
}
// Ocitavanje grupe podataka sa terminala, za brojilo sa datim serijskim brojem.
// Grupa podataka je definisana flegovima.
// Ocitane podatke vraca preko parametra cKorisniPodaci. U slucaju neuspeha vraca false.
bool KKomunikator::OcitajGrupuPodataka( unsigned int nFlegovi, unsigned int nSerijskiBroj,
string& cKorisniPodaci ){
bool izlaz = false;
// Inicijalizuj transakciju
ResetujTransakciju( string( "Ocitavanje svih podataka" ) );
// Formiraj komandu ( poruku formata FP_KOMANDA_TERMINALU ) koja se salje terminalu
DodajKomandnuPoruku( KT_OCITAJ_SVE_PODATKE, false, nSerijskiBroj );
// Prodji kroz spisak komandi i uzmi one koje se traze
TSpisakKomandi::iterator sk_iter = KSpisakKomandi::Instance()->SpisakKomandi.begin();
TSpisakKomandi::iterator sk_iterEnd = KSpisakKomandi::Instance()->SpisakKomandi.end();
KKomanda komanda;
while ( sk_iter != sk_iterEnd ) {
if ( sk_iter->nPodatakFleg & nFlegovi ) {
unsigned int nDuzinaOdgovora;
IDFormataPoruke formatOdgovora;
unsigned int nPodatakFleg;
// Formiraj poruku za odgovor od terminala
KSpisakKomandi::Instance()->DajOpisKomande( sk_iter->IDkomande, adminInfo,
nDuzinaOdgovora,
formatOdgovora,
nPodatakFleg );
if ( adminInfo.bDodatniOpisRT ) {
// Nova verzija :
// odgovor od terminala je poruka koja se sastoji od sledecih komponenti :
// - poruka pocinje sa start bajtom i ID-om;
// - zatim sledi 1 bajt koji definise duzinu ocitanog podatka;
// - iza toga slede bajtovi samog podatka; duzina ovog dela
// se dobija iz 'opisa rucnog terminala' ( opisTerminala )
// - na kraju ide 1 bajt za sumu
// Znaci, duzina odgovora je :
nDuzinaOdgovora = OVERH + opisTerminala.DuzinaPodataka( sk_iter->nPodatakFleg );
DodajPorukuZaOdgovor( nDuzinaOdgovora, false, formatOdgovora );
}
else {
// Stara verzija
DodajPorukuZaOdgovor( nDuzinaOdgovora, false, formatOdgovora );
}
}
sk_iter ++;
}
// Izvrsi transakciju
izlaz = ProcitajPodatkeSaTerminala( cKorisniPodaci );
return izlaz;
}
// Preuzima 'administrativne' informacije sa rucnog terminala.
// U slucaju neuspeha vraca false.
// nDuzinaOdg ( duzina odgovora ) zavisi od verzije softvera na rucnom terminalu.
bool KKomunikator::OcitajOpisRT( void ) {
bool izlaz = false;
// Procitaj ADMIN_INFO sa terminala
string cPodaci;
// NAPOMENA: pri pozivu procedure OcitajPodatak moram da zadam duzinu odgovora
// ( u suprotnom, procedura ce da poveca duzinu za 1 pa ocitavanje nece da uspe )
if ( OcitajPodatak( KT_OCITAVANJE_OPISA_RT, 0, cPodaci, OVERH+BROJ_BAJTOVA_ZA_OPIS_RT ) ) {
KInterpret::Instance()->IzdvojiOpisRT( cPodaci, opisTerminala );
izlaz = true;
}
else {
opisTerminala.Reset();
}
return izlaz;
}
// Preuzima 'administrativne' informacije sa rucnog terminala.
// U slucaju neuspeha vraca false.
bool KKomunikator::OcitajAdminInfo( void ) {
bool izlaz = false;
// Najpre pokusaj najnoviju verziju
izlaz = OcitajAdminInfoDateDuzine( OVERH + BROJ_BAJTOVA_ZA_ADMIN_INFO_11 );
// Ako ne uspe, probaj staru verziju
if ( !izlaz ) izlaz = OcitajAdminInfoDateDuzine( OVERH + BROJ_BAJTOVA_ZA_ADMIN_INFO_10 );
return izlaz;
}
// Preuzima 'administrativne' informacije sa rucnog terminala.
// U slucaju neuspeha vraca false.
// nDuzinaOdg ( duzina odgovora ) zavisi od verzije softvera na rucnom terminalu.
bool KKomunikator::OcitajAdminInfoDateDuzine( unsigned int nDuzinaOdg ) {
bool izlaz = false;
// Procitaj ADMIN_INFO sa terminala
string cPodaci;
if ( OcitajPodatak( KT_OCITAJ_ADMIN_INFO, 0, cPodaci, nDuzinaOdg ) ) {
KInterpret::Instance()->IzdvojiAdminInfo( cPodaci, adminInfo );
adminInfo.Prikljuci();
izlaz = true;
}
else {
adminInfo.Reset();
adminInfo.Otkaci();
}
return izlaz;
}
// Ocitavanje tarife koja treba da se setuje na brojilima. U slucaju neuspeha vraca false.
bool KKomunikator::OcitajMasterTarifu( string& cKorisniPodaci ){
return OcitajPodatak( KT_OCITAJ_MASTER_TARIFU, 0, cKorisniPodaci,
OVERH+BROJ_BAJTOVA_ZA_MASTER_TARIFU );
}
// Ocitavanje sve podataka sa terminala, za brojilo sa datim serijskim brojem.
// Grupu podataka definisu flegovi koje treba setovati pozivom procedure 'OcitajAdminInfo'.
// Ocitane podatke vraca preko parametra cKorisniPodaci. U slucaju neuspeha vraca false.
bool KKomunikator::OcitajSvePodatake( unsigned int nSerijskiBroj, string& cKorisniPodaci ){
return OcitajGrupuPodataka( adminInfo.nKontrolniFlegovi, nSerijskiBroj, cKorisniPodaci );
}
// Ocitavanje spiska brojila sa rucnog terminala.
// Ocitane podatke vraca preko parametra cKorisniPodaci. U slucaju neuspeha vraca false.
bool KKomunikator::OcitajSpisakBrojila( string& cKorisniPodaci ){
bool izlaz = false;
// Terminal salje spisak brojila u delovima ( 'paketima' ). ciju velicinu treba odrediti :
unsigned int nDuzinaElementaSpiska = adminInfo.DuzinaElementaSpiska();
unsigned int nMaxBrElemSpiskaUPaketu = adminInfo.MaxBrElemSpiskaUPaketu();
unsigned int nVelicinaCelogPaketa = 3 + nMaxBrElemSpiskaUPaketu * nDuzinaElementaSpiska;
unsigned int nPotrebanBrojCelihPaketa = adminInfo.nBrojBrojilaUSpisku / nMaxBrElemSpiskaUPaketu;
unsigned int nBrojBrojilaZaPoslednjiPaket = adminInfo.nBrojBrojilaUSpisku % nMaxBrElemSpiskaUPaketu;
unsigned int nVelicinaPoslednjegPaketa = 3 + nBrojBrojilaZaPoslednjiPaket * nDuzinaElementaSpiska;
KKomanda komanda;
KSpisakKomandi::Instance()->DajKomandu( KT_OCITAJ_SPISAK_BROJILA, komanda );
// Inicijalizuj transakciju
ResetujTransakciju( string( "Ocitavanje spiska brojila" ) );
// Formiraj komandu ( poruku formata FP_KOMANDA_TERMINALU ) koja se salje terminalu
DodajKomandnuPoruku( KT_OCITAJ_SPISAK_BROJILA, false );
// Formiraj poruke za pakete koji se primaju sa terminala :
// - najpre za paketa 'pune duzine' :
for ( int i = 0; i < nPotrebanBrojCelihPaketa; i++ )
DodajPorukuZaOdgovor( nVelicinaCelogPaketa, false, komanda.formatOdgovora );
// - na kraju za paket sa preostalim brojilima
if ( nBrojBrojilaZaPoslednjiPaket > 0 )
DodajPorukuZaOdgovor( nVelicinaPoslednjegPaketa, false, komanda.formatOdgovora );
// Izvrsi transakciju
izlaz = ProcitajPodatkeSaTerminala( cKorisniPodaci );
return izlaz;
}
// Ocitava trazene podatke za sva brojila u spisku 'spisakBrojila'.
// Ocitane podatke vraca preko vektora 'korisniPodaci'. U slucaju neuspeha vraca false.
bool KKomunikator::OcitajPodatkeZaBrojilaIzSpiska( TSpisakBrojila& spisakBrojila, EIDKomande IDkomande,
TListaStringova& korisniPodaci ){
bool izlaz = true;
korisniPodaci.clear();
TSpisakBrojila::iterator sb_iter = spisakBrojila.begin();
TSpisakBrojila::iterator sb_iterEnd = spisakBrojila.end();
string cKorisniPodaci;
while( sb_iter != sb_iterEnd ) {
unsigned int nSerijskiBroj = sb_iter->nSerijskiBrojBrojila;
if ( IDkomande == KT_OCITAJ_SVE_PODATKE ) {
if ( !OcitajSvePodatake( nSerijskiBroj, cKorisniPodaci ) ){
izlaz = false;
break;
}
}
else {
if ( !OcitajPodatak( IDkomande, nSerijskiBroj, cKorisniPodaci ) ){
izlaz = false;
break;
}
}
// Na pocetku svakog stringa je serijski broj brojila ( 4 znaka = 8 BCD cifre )
korisniPodaci.push_back( KKorisno::Instance()->KonvertIntUString( nSerijskiBroj, 4 )
+ cKorisniPodaci );
sb_iter++;
}
return izlaz;
}
// Ocitava trazene podatke za sva brojila u spisku koji se nalazi u rucnom terminalu.
// Ocitane podatke vraca preko vektora 'korisniPodaci'. U slucaju neuspeha vraca false.
bool KKomunikator::OcitajPodatakZaSvaBrojila( EIDKomande IDkomande, TListaStringova& korisniPodaci ){
bool izlaz = false;
string cKorisniPodaci;
if ( OcitajAdminInfo() ) {
if ( OcitajSpisakBrojila( cKorisniPodaci ) ) {
TSpisakBrojila spisakBrojila;
KInterpret::Instance()->IzdvojiSpisakBrojila( cKorisniPodaci, adminInfo,
spisakBrojila );
if( OcitajPodatkeZaBrojilaIzSpiska( spisakBrojila, IDkomande, korisniPodaci ) )
izlaz = true;
}
}
return izlaz;
}
// Izvrsava komandu za snimanje datog podatka na rucni terminal.
// U slucaju neuspeha vraca false.
bool KKomunikator::SnimiNaTerminal( EIDKomande ID, string cPodatak ){
bool izlaz = false;
// Inicijalizuj transakciju
ResetujTransakciju( string( "Setovanje terminala" ) );
// Formiraj komandu ( poruku formata FP_KOMANDA_TERMINALU ) koja se salje terminalu
DodajKomandnuPoruku( ID, false );
// Formiraj poruku za prijem potvrde od terminala da je spreman da primi sledeci podatak
DodajPorukuZaOdgovor( 3, false, FP_POTVRDA_SA_TERMINALA );
// Formiraj poruku sa podacima koji se salju terminalu
DodajPorukuPodatakaZaTerminal( ID, false, cPodatak );
// Formiraj poruku za potvrdu koju salje terminal da je primio podatke
DodajPorukuZaOdgovor( 3, false, FP_POTVRDA_SA_TERMINALA );
// Izvrsi transakciju
izlaz = IzvrsiTransakciju();
return izlaz;
}
// Izvrsava komandu za snimanje lozinke na rucni terminal.
// Ako rucni terminal podrzava i proveru 'ID-a PC aplikacije' onda treba zadati i taj ID.
// U slucaju neuspeha vraca false.
bool KKomunikator::SnimiLozinkuNaTerminal( EIDKomande ID, string cLozinke,
bool PodrzanPCAppID, string cAppID ){
bool izlaz = false;
// Inicijalizuj transakciju
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -