Modo Online
Dispositivos que suportam esta função:
Dispositivos | Firmware |
---|---|
SS 5530 | 220708 ou superior |
SS 5530 LITE | 230307 ou superior |
SS 3532 MF W | 20231018 ou superior |
SS 3542 MF W | 20231018 ou superior |
SS 5531 MF W | 20231018 ou superior |
SS 5541 MF W | 20231018 ou superior |
SS 5532 MF W | 20231018 ou superior |
SS 5542 MF W | 20231018 ou superior |
SS 3540 MF BIO | 231129 ou superior |
SS 3540 MF | 231129 ou superior |
SS 3530 MF | 20240601 ou superior |
SS 3530 MF W | 20240601 ou superior |
SS 3430 Bio | 20240315 ou superior |
SS 3430 MF Bio | 20240315 ou superior |
Importante: Para o funcionamento correto do Modo Online é necessário que o dispositivo esteja configurado com o Feedback no modo "Personalizado".
O Modo Online permite que o dispositivo sempre “pergunte” ao servidor se pode liberar ou negar acesso ao usuário que está tentando acessar determinado ponto de acesso e caso a conexão com o servidor for perdida, operar com lista de usuários liberados (Lista Branca).
O Modo Online possui dois estados: Online e Offline. Cada um terá um fluxo de decisão específico.
Através da integração do modo online algumas funções são possiveis de implementação, tais como:
- Antipassback global
- Intertravemento global
- Acesso manual
- Antipassback apenas com supervisão
- Bloqueio de acesso
- Chamada antecipada
- Controle de refeição
- Controle de trânsito
- Escolta
- Escolta com dupla passagem
- Revista aleatória
Keep Alive
O dispositivo tentará uma requisição GET no “Keep alive path”, se a resposta retornada pelo servidor for Código 200 OK, então o dispositivo estará no “Estado Online”, caso a resposta do servidor for algo diferente ou atingir o tempo limite, então o dispositivo entrará no “Estado Offline”. O dispositivo repetirá esse processo com base no “Keep Alive Time”.
Diagrama de operação do Keep Alive:
Estado Online
Quando o dispositivo estiver no estado online, a todos que tentarem acessar o dispositivo, ele postará o evento e aguardará um response do servidor (resposta de autorização) contendo três campos: id
, auth
e message
.
Para credenciais biométricas, o dispositivo verificará se o usuário está cadastrado antes de enviar para o servidor. Se não for, acesso negado.
Para senhas e cartões, mesmo que o usuário não esteja cadastrado, a solicitação de autorização será enviada ao servidor. O servidor responderá à solicitação com um JSON conforme descrito anteriormente. No caso de um TIMEOUT
, o dispositivo decidirá com base nos usuários inscritos e o dispositivo mudará para o estado offline. O TIMEOUT
é um parâmetro na interface web.
O fluxo abaixo ilustra a explicação.
As requisições POST realizadas pelo dispositivo ao servidor deverão ser respondidas de acordo com o seguinte JSON, contendo as informações:
{
"message": "Seja Bem vindo!",
"code": "200",
"auth": "true"
}
param | type | description |
---|---|---|
message * | String | Mensagem que será exibida no display |
code * | Number | Código sempre é 200 |
auth * | String | String true/false corresponde se a porta irá ser acionada ou não. |
Estado Offline
Quando o dispositivo estiver no estado offline, para todas as tentativas de acesso ao dispositivo, ele decidirá com base nos usuários cadastrados. No estado offline, todos os usuários têm privilégios VIP, 24 horas por dia, 7 dias por semana.
Servidor de Exemplo
O servidor de exemplo realiza a configuração de duas rotas, sendo a /notifications para receber os eventos e aprovar/negar os acessos e /keepalive para a verificação pelo dispositivo do estado do servidor.
# -*- coding:utf-8 -*-
from flask import Flask,request, jsonify
import json
import ast
import sys, os
import time
app = Flask(__name__)
@app.route('/notification', methods = ['POST'])
def event_receiver():
if request.method == 'POST':
res = request.data
data_list = res.split(b"--myboundary\r\n")
if data_list:
for a_info in data_list:
if b"Content-Type" in a_info:
lines = a_info.split(b"\r\n")
a_type = lines[0].split(b": ")[1]
if a_type == b"image/jpeg":
image_data = b"\r\n".join(lines[3:-3])
else:
text_data = b"\r\n".join(lines[3:-1])
evento_str = text_data.decode("utf-8")
evento_dict = ast.literal_eval(evento_str.replace("--myboundary--", " "))
json_object = json.dumps(evento_dict, indent = 4)
resp_dict = json.loads(json_object)
print(resp_dict)
event_code = resp_dict.get("Events")[0].get('Code')
print("################## ", event_code, " ##################")
if event_code == "AccessControl":
event_data = resp_dict.get("Events")[0].get('Data')
card_name = event_data.get('CardName')
card_no = event_data.get('CardNo')
card_type = event_data.get('CardType')
door = event_data.get('Door')
error_code = event_data.get('ErrorCode')
method = event_data.get('Method')
reader_id = event_data.get('ReaderID')
event_status = event_data.get('Status')
event_type = event_data.get('Type')
event_entry = event_data.get('Entry')
event_utc = event_data.get('UTC')
user_id = event_data.get('UserID')
user_type = event_data.get('UserType')
pwd = event_data.get('DynPWD')
print("UserID: ", user_id)
print("UserType", user_type)
print("CardName: ", card_name)
print("CardNo: ", card_no)
print("CardType: ", card_type)
print("Password: ", pwd)
print("Door: ", door)
print("ErrorCode: ", error_code)
print("Method: ", method)
print("ReaderID: ", reader_id)
print("Status: ", event_status)
print("Type: ", event_type)
print("Entry: ", event_entry)
print("UTC: ", event_utc)
print(49 * "#")
# TESTE DE REGRAS
time.sleep(1)
if user_id == 6:
return jsonify({"message": "Pagamento não realizado! Consulte a secretaria!", "code": "200", "auth": "false"})
elif card_no in ["EC56D271", "09201802"]:
return jsonify({"message": "Voce está bloqueado", "code": "200", "auth": "false"})
elif pwd != None:
if int(pwd) == 22:
return jsonify({"message": "Acesso Liberado", "code": "200", "auth": "true"})
elif event_code == "DoorStatus":
event_data = resp_dict.get("Events")[0].get('Data')
door_status = event_data.get('Status')
door_utc = event_data.get('UTC')
print("Door Status: ", door_status)
print("UTC", door_utc)
print(49 * "#")
return jsonify({"message": "", "code": "200", "auth": "false"})
elif event_code == "BreakIn":
event_data = resp_dict.get("Events")[0].get('Data')
door_name = event_data.get('Name')
door_utc = event_data.get('UTC')
print("Door Name: ", door_name)
print("UTC", door_utc)
print(49 * "#")
return jsonify({"message": "", "code": "200", "auth": "false"})
return jsonify({"message": "", "code": "200", "auth": "false"})
'''
O retorno deverá ser um JSON, contendo as informações:
"message": "", // Mensagem que será exibida no display
"code": "200", // Código sempre é 200.
"auth": "", Boolean, corresponde se a porta irá ser acionada ou não.
'''
@app.route('/keepalive', methods = ['GET'])
def keep_alive():
return "OK"
'''
Deverá ser retornado qualquer request que contenha código 200.
'''
# Server Start
if __name__ == '__main__':
app.run(host='192.168.3.14', debug=True, port=3000)
Comando para Limpar Eventos em Cache
Caso você possua muitos eventos, tanto no modo servidor de envio de eventos quanto no modo online que não foi feito a confirmação de envio ao servidor e deseja apagar todos os eventos em cache, você pode utilizar o comando abaixo.
Requisição - GET
http://19.168.3.87/cgi-bin/recordUpdater.cgi?action=clear&name=AccessOffline
param | type | description |
---|---|---|
clear * | String | Comando para Limpar |
Exemplo de Retorno - text/plain:
OK
Exemplos de Servidor
python Em desenvolvimento...