Magazyny zasobów ochrony ludności mieszczą się często w piwnicach albo budynkach o grubych ścianach, gdzie zasięg sieci komórkowej jest słaby albo go nie ma. Aplikacja wymagająca stałego połączenia zatrzymałaby wydanie zasobu w chwili, gdy jest ono najpilniejsze.

OLiOC Mobile, aplikacja WMS OLiOC na Androida, zapisuje operacje w bazie na urządzeniu i przesyła je do serwera po odzyskaniu łączności. Takie podejście rozwiązuje problem zasięgu, ale tworzy dwa nowe: powtórzenia przy ponownej wysyłce oraz konflikty, gdy dwa urządzenia zmienią tę samą pozycję bez kontaktu z serwerem.

Tryb offline nie jest bezkonfliktowy. Dwa terminale bez łączności mogą wydać ostatnią sztukę tego samego zasobu. Synchronizacja nie zapobiegnie takiej sytuacji, może ją tylko wykryć i przekazać do wyjaśnienia, dlatego reguły rozstrzygania konfliktów trzeba ustalić przed wdrożeniem.

Zakres pracy bez połączenia

Aplikacja obsługuje bez połączenia cztery rodzaje operacji. Każda niesie inne ryzyko przy późniejszej synchronizacji.

OperacjaZapis na urządzeniuRyzyko przy synchronizacji
Przyjęcie zasobudokument z identyfikatorem nadanym na urządzeniuponowna wysyłka po zerwaniu połączenia
Wydanie kryzysowe WK-ZOLdokument podpisany na ekranie przez odbierającegowydanie tej samej sztuki z dwóch terminali
Inwentaryzacjawynik spisu z datą oraz osobą spisującąspis, który nie uwzględnia operacji z innego urządzenia
Elektroniczna lista kontrolnawynik przeglądu sprzętuta sama pozycja oceniona na dwóch urządzeniach

Przebieg wydania kryzysowego opisuje artykuł o wydawaniu zasobów pod presją czasu, a listy kontrolne - materiał o konserwacji sprzętu OC w WMS OLiOC. Inaczej działa aplikacja mobilna BioKontrol, która wymaga stałego połączenia, bo kierowca pracuje w terenie z zasięgiem, a system blokuje zrzut na podstawie danych z serwera.

Urządzenia i skanowanie

Aplikacja działa na smartfonach i tabletach z Androidem, w tym na wzmocnionych urządzeniach Zebra oraz Panasonic z serii Toughbook. Przy wyborze sprzętu warto sprawdzić cztery parametry.

  • Szczelność obudowy - klasa IP65 albo IP67 według normy IEC 60529, czyli ochrona przed pyłem oraz strugą wody albo krótkim zanurzeniem.
  • Odporność mechaniczna - deklaracja producenta o testach według MIL-STD-810, amerykańskiej normy metod badań; to opis przeprowadzonych prób, a nie certyfikat, więc warto sprawdzić, które testy objęły dany model.
  • Skaner - wbudowany czytnik kodów kreskowych i QR; w urządzeniach Zebra wynik skanu trafia do aplikacji przez usługę DataWedge.
  • Wersja systemu - materiały produktu podają Androida 8.0 jako minimum, a ta wersja od lat nie otrzymuje poprawek bezpieczeństwa, więc warto wybierać urządzenia z aktualnym systemem i deklarowanym okresem wsparcia.

Dane zapisane offline zostają na urządzeniu do czasu synchronizacji. Szyfrowanie pamięci oraz możliwość zdalnego wyczyszczenia zgubionego terminala przez system zarządzania urządzeniami chronią ewidencję przed ujawnieniem.

Synchronizacja: operacje w górę, zmiany w dół

Diagram synchronizacji OLiOC Mobile w czterech krokach: operacja zapisana offline z identyfikatorem i numerem kolejnym, wysyłka paczki operacji, jednokrotny zapis na serwerze, zmiany odsyłane do urządzenia
Synchronizacja OLiOC Mobile: operacje w górę, zmienione wiersze w dół

Urządzenie nie wysyła stanów magazynowych, tylko operacje: przyjęcie o 10 sztuk, wydanie 4 sztuk. Każda operacja ma identyfikator nadany na urządzeniu oraz kolejny numer w obrębie urządzenia. Serwer zapisuje operację tylko raz, więc ponowienie wysyłki po zerwanym połączeniu nie zmienia stanu. Schemat w T-SQL ilustruje zasadę, a nie kod WMS OLiOC.

CREATE TABLE dbo.OperacjaMagazynowa (
    OperacjaId     uniqueidentifier NOT NULL PRIMARY KEY,  -- nadany na urządzeniu
    UrzadzenieId   int              NOT NULL,
    NrKolejny      int              NOT NULL,             -- licznik operacji urządzenia
    ZasobId        int              NOT NULL,
    Zmiana         decimal(12, 3)   NOT NULL,             -- przyjęcie dodatnie, wydanie ujemne
    CzasUrzadzenia datetime2        NOT NULL,
    CzasSerwera    datetime2        NOT NULL DEFAULT SYSUTCDATETIME(),
    CONSTRAINT UQ_Operacja_Urzadzenie UNIQUE (UrzadzenieId, NrKolejny)
);

INSERT INTO dbo.OperacjaMagazynowa (OperacjaId, UrzadzenieId, NrKolejny, ZasobId, Zmiana, CzasUrzadzenia)
SELECT p.OperacjaId, p.UrzadzenieId, p.NrKolejny, p.ZasobId, p.Zmiana, p.CzasUrzadzenia
  FROM @Paczka AS p
 WHERE NOT EXISTS (SELECT 1 FROM dbo.OperacjaMagazynowa AS o WHERE o.OperacjaId = p.OperacjaId);

Jeżeli dwie kopie tej samej paczki dotrą jednocześnie, obie mogą przejść test NOT EXISTS, ale klucz główny odrzuci drugą błędem 2627, a ponowiona paczka zostanie już odfiltrowana.

Numer kolejny ujawnia operacje, które nigdy nie dotarły: luka między numerami 41 i 43 jednego urządzenia oznacza zgubioną operację 42, na przykład po resecie terminala. Zapis dwóch znaczników czasu wynika z tego, że zegar urządzenia pracującego tygodniami bez sieci może się rozjechać, a czas serwera pokazuje tylko moment przyjęcia paczki.

W drugą stronę serwer wysyła urządzeniu tylko wiersze zmienione od jego ostatniej synchronizacji. Mechanizm Change Tracking w SQL Server zwraca klucze zmienionych wierszy od podanej wersji, a odczyt w transakcji SNAPSHOT gwarantuje, że lista zmian i nowy numer wersji pochodzą z tego samego stanu bazy.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRANSACTION;
    DECLARE @NowaWersja bigint = CHANGE_TRACKING_CURRENT_VERSION();

    IF @OstatniaWersja < CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.Zasob'))
        THROW 50070, N'Historia zmian nie sięga wersji urządzenia. Wymagana pełna synchronizacja.', 1;

    SELECT ct.ZasobId, ct.SYS_CHANGE_OPERATION, z.Nazwa, z.TerminWaznosci
      FROM CHANGETABLE(CHANGES dbo.Zasob, @OstatniaWersja) AS ct
      LEFT JOIN dbo.Zasob AS z ON z.ZasobId = ct.ZasobId;

    SELECT @NowaWersja AS NowaWersja;
COMMIT;

Warunek z funkcją CHANGE_TRACKING_MIN_VALID_VERSION chroni przed cichą utratą zmian. Terminal wyłączony dłużej niż okres przechowywania historii zmian musi pobrać pełny stan, bo różnica od jego wersji nie jest już dostępna. Usunięty wiersz wraca z kolumną SYS_CHANGE_OPERATION równą 'D' i pustymi danymi, dlatego złączenie jest zewnętrzne.

Konflikt dwóch wydań tej samej pozycji

Dwa terminale bez łączności widzą stan 1 sztuki i oba ją wydają. Po synchronizacji suma operacji daje stan -1. Zapytanie sumuje operacje narastająco i wskazuje miejsca, w których stan spadł poniżej zera.

SELECT x.ZasobId, x.OperacjaId, x.UrzadzenieId, x.CzasUrzadzenia, x.StanPo
  FROM (SELECT o.ZasobId, o.OperacjaId, o.UrzadzenieId, o.CzasUrzadzenia,
               SUM(o.Zmiana) OVER (PARTITION BY o.ZasobId
                                   ORDER BY o.CzasUrzadzenia, o.OperacjaId
                                   ROWS UNBOUNDED PRECEDING) AS StanPo
          FROM dbo.OperacjaMagazynowa AS o) AS x
 WHERE x.StanPo < 0;

Kolejność według czasu urządzenia jest przybliżona z powodu dryfu zegarów, więc wynik wskazuje pozycje do wyjaśnienia, a nie winnego. Przy wydaniu kryzysowym pierwszeństwo ma wydanie, a konflikt staje się zadaniem uzgodnienia po zdarzeniu. Przy planowanych dystrybucjach można mu zapobiec przydziałem ilości: przed wyjazdem każde urządzenie dostaje limit, którego suma nie przekracza stanu, i wydaje offline tylko w jego granicach. Zasady prowadzenia stanów opisuje artykuł o magazynie zasobów ochrony ludności.

Interfejs do pracy w rękawicach

Materiały produktu podają minimalny rozmiar przycisku 80 px. Na Androidzie rozmiar trzeba jednak określać w dp, czyli pikselach niezależnych od gęstości ekranu. Na ekranie o gęstości 3x 80 fizycznych pikseli to około 27 dp, mniej niż 48 dp, które dokumentacja dostępności aplikacji na Androida zaleca jako minimum dla każdego elementu dotykowego. Do pracy w grubych rękawicach przyciski powinny być wyraźnie większe od tego minimum.

Kryterium WCAG 2.2PoziomWymaganie
1.4.3 Kontrast (minimum)AA4,5:1 dla zwykłego tekstu
1.4.6 Kontrast (wzmocniony)AAA7:1 dla zwykłego tekstu
2.5.8 Rozmiar celu (minimum)AA24 na 24 piksele CSS
2.5.5 Rozmiar celu (wzmocniony)AAA44 na 44 piksele CSS

Źródło deklaruje zgodność trybu alarmowego z poziomem AAA. Specyfikacja WCAG 2.2 zaznacza, że nie zaleca wymagania poziomu AAA dla całych serwisów, bo części kryteriów nie da się spełnić dla niektórych treści. Precyzyjniejsza deklaracja wskazuje konkretne kryteria spełnione w trybie alarmowym, na przykład kontrast 7:1 oraz rozmiar celu co najmniej 44 na 44.

Wskazanie lokalizacji przy kompletacji

Klasyczny system put-to-light używa modułów świetlnych zamontowanych przy lokalizacjach magazynowych: lampka zapala się przy półce, na którą trzeba odłożyć albo z której trzeba pobrać zasób. OLiOC Mobile wyświetla lokalizację oraz ilość na ekranie urządzenia, więc nie wymaga instalacji na regałach. Ceną jest konieczność patrzenia na ekran przy każdej pozycji, co przy masowym wydaniu dla wielu formacji wydłuża kompletację w porównaniu z sygnalizacją świetlną.

Operacje zsynchronizowane z terminali trafiają do zestawienia zmian dla ewidencji centralnej, co opisuje artykuł o ewidencji zasobów i CEZOLOC. Stan po synchronizacji jest też podstawą raportu pokrycia normy 3-dniowej, a partie z terminem ważności, spisywane w magazynie z terminala, omawia materiał o kontroli terminów ważności w magazynie ochrony ludności. Pełny opis systemu zawiera strona WMS OLiOC.

Pytania i odpowiedzi

Czy aplikacja działa w magazynie bez zasięgu

Tak. Operacje są zapisywane w bazie na urządzeniu, a aplikacja przesyła je do serwera WMS OLiOC po odzyskaniu łączności, bez udziału magazyniera.

Co się stanie, gdy ta sama operacja zostanie wysłana dwa razy

Nic. Każda operacja ma identyfikator nadany na urządzeniu, a serwer pomija operację o identyfikatorze, który już zapisał. Ponowna wysyłka po zerwaniu połączenia nie tworzy duplikatu.

Co jeśli dwa terminale bez łączności wydadzą ten sam zasób

Po synchronizacji stan pozycji spadnie poniżej zera, a system wskaże operacje, które do tego doprowadziły. Synchronizacja wykrywa taki konflikt, ale nie może mu zapobiec, dlatego przy planowanych wydaniach warto przydzielić urządzeniom ilości z góry.

Na jakich urządzeniach działa OLiOC Mobile

Na smartfonach i tabletach z Androidem, w tym na wzmocnionych urządzeniach Zebra oraz Panasonic z wbudowanym skanerem kodów. Warto wybierać urządzenia z aktualną wersją systemu i deklarowanym okresem wsparcia producenta.

Czy przyciski o wielkości 80 px wystarczą do pracy w rękawicach

To zależy od gęstości ekranu. Na ekranie o gęstości 3x 80 fizycznych pikseli to około 27 dp, czyli mniej niż zalecane przez Google 48 dp. Rozmiar przycisków trzeba określać w dp, a nie w pikselach.

Słownik pojęć

Offline-first
Architektura, w której aplikacja zapisuje dane najpierw na urządzeniu i traktuje brak połączenia jako stan normalny. Synchronizacja z serwerem następuje po odzyskaniu łączności.
Idempotencja
Właściwość operacji, której wielokrotne wykonanie daje ten sam wynik co jednokrotne. Chroni przed duplikatami przy ponawianiu wysyłki.
Change Tracking
Mechanizm SQL Server zapisujący, które wiersze tabeli zmieniły się od podanej wersji. Pozwala wysłać urządzeniu tylko zmiany od jego ostatniej synchronizacji.
dp
Piksel niezależny od gęstości ekranu w systemie Android. Jeden dp odpowiada jednemu pikselowi na ekranie o gęstości 160 dpi.
Przydział ilości
Ilość zasobu, którą urządzenie może wydać bez połączenia z serwerem. Suma przydziałów nie przekracza stanu, więc wydania offline nie prowadzą do stanu ujemnego.