mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
calibre: rework connection setup
Faster and with better UI:
- roughly halve a successful connection setup
- drop manual & temporary TCP connection before the real ZMQ one:
- it slows down the total connection time
- it's actually counted by calibre as a failed connection attempt:
after 5 consecutive failures from the same IP, calibre ignore
further connections, with no feedback to the user, except an
error trace, until the wireless server is restarted
- avoid unconditional 1s delay before checking for authentication failure
- "searching" & "connecting" (cancellable) dialogs
- stop connection on quit / restart
This commit is contained in:
committed by
Martín Fernández
parent
3768de6717
commit
8fef5c1766
@@ -37,43 +37,27 @@ function Calibre:onCalibreBrowseBy(field)
|
||||
end
|
||||
|
||||
function Calibre:onNetworkDisconnected()
|
||||
self:closeWirelessConnection()
|
||||
CalibreWireless:disconnect()
|
||||
end
|
||||
|
||||
function Calibre:onSuspend()
|
||||
self:closeWirelessConnection()
|
||||
CalibreWireless:disconnect()
|
||||
end
|
||||
|
||||
function Calibre:onClose()
|
||||
self:closeWirelessConnection()
|
||||
CalibreWireless:disconnect()
|
||||
end
|
||||
|
||||
function Calibre:onCloseWidget()
|
||||
CalibreWireless:disconnect()
|
||||
end
|
||||
|
||||
function Calibre:onStartWirelessConnection()
|
||||
UIManager:nextTick(function()
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("Connecting to calibre"),
|
||||
timeout = 2,
|
||||
})
|
||||
end)
|
||||
UIManager:tickAfterNext(function()
|
||||
self:startWirelessConnection()
|
||||
end)
|
||||
CalibreWireless:connect()
|
||||
end
|
||||
|
||||
function Calibre:onCloseWirelessConnection()
|
||||
self:closeWirelessConnection()
|
||||
end
|
||||
|
||||
function Calibre:startWirelessConnection()
|
||||
if not CalibreWireless.calibre_socket then
|
||||
CalibreWireless:connect()
|
||||
end
|
||||
end
|
||||
|
||||
function Calibre:closeWirelessConnection()
|
||||
if CalibreWireless.calibre_socket then
|
||||
CalibreWireless:disconnect()
|
||||
end
|
||||
CalibreWireless:disconnect()
|
||||
end
|
||||
|
||||
function Calibre:onDispatcherRegisterActions()
|
||||
|
||||
@@ -13,6 +13,7 @@ local FFIUtil = require("ffi/util")
|
||||
local InputDialog = require("ui/widget/inputdialog")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local NetworkMgr = require("ui/network/manager")
|
||||
local Trapper = require("ui/trapper")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||
local lfs = require("libs/libkoreader-lfs")
|
||||
@@ -25,6 +26,58 @@ local T = FFIUtil.template
|
||||
|
||||
require("ffi/zeromq_h")
|
||||
|
||||
-- calibre broadcast ports used to find calibre server
|
||||
local BROADCAST_PORTS = {54982, 48123, 39001, 44044, 59678}
|
||||
-- calibre companion local port
|
||||
local COMPANION_PORT = 8134
|
||||
-- requests opcodes
|
||||
local OPCODES = {
|
||||
OK = 0,
|
||||
SET_CALIBRE_DEVICE_INFO = 1,
|
||||
SET_CALIBRE_DEVICE_NAME = 2,
|
||||
GET_DEVICE_INFORMATION = 3,
|
||||
TOTAL_SPACE = 4,
|
||||
FREE_SPACE = 5,
|
||||
GET_BOOK_COUNT = 6,
|
||||
SEND_BOOKLISTS = 7,
|
||||
SEND_BOOK = 8,
|
||||
GET_INITIALIZATION_INFO = 9,
|
||||
BOOK_DONE = 11,
|
||||
NOOP = 12,
|
||||
DELETE_BOOK = 13,
|
||||
GET_BOOK_FILE_SEGMENT = 14,
|
||||
GET_BOOK_METADATA = 15,
|
||||
SEND_BOOK_METADATA = 16,
|
||||
DISPLAY_MESSAGE = 17,
|
||||
CALIBRE_BUSY = 18,
|
||||
SET_LIBRARY_INFO = 19,
|
||||
ERROR = 20,
|
||||
}
|
||||
|
||||
-- Mark some strings for translation.
|
||||
-- luacheck: push ignore 511
|
||||
if false then
|
||||
-- @translators tcp socket error on host:port
|
||||
_("no route to host")
|
||||
-- @translators tcp socket error on host:port
|
||||
_("host not found")
|
||||
-- @translators tcp socket error on host:port
|
||||
_("connection refused")
|
||||
-- @translators tcp socket error on host:port
|
||||
_("timeout")
|
||||
-- @translators tcp socket error on host:port
|
||||
_("closed")
|
||||
-- @translators calibre server address type
|
||||
_("discovered")
|
||||
-- @translators calibre server address type
|
||||
_("specified")
|
||||
-- @translators calibre connection error
|
||||
_("handshake timeout")
|
||||
-- @translators calibre connection error
|
||||
_("invalid password")
|
||||
end
|
||||
-- luacheck: pop
|
||||
|
||||
-- supported formats
|
||||
local extensions = CalibreExtensions:get()
|
||||
|
||||
@@ -56,51 +109,20 @@ local CalibreWireless = WidgetContainer:extend{
|
||||
id = "KOReader",
|
||||
model = require("device").model,
|
||||
version = require("version"):getCurrentRevision(),
|
||||
-- calibre companion local port
|
||||
port = 8134,
|
||||
-- calibre broadcast ports used to find calibre server
|
||||
broadcast_ports = {54982, 48123, 39001, 44044, 59678},
|
||||
opcodes = {
|
||||
NOOP = 12,
|
||||
OK = 0,
|
||||
ERROR = 20,
|
||||
BOOK_DONE = 11,
|
||||
CALIBRE_BUSY = 18,
|
||||
SET_LIBRARY_INFO = 19,
|
||||
DELETE_BOOK = 13,
|
||||
DISPLAY_MESSAGE = 17,
|
||||
FREE_SPACE = 5,
|
||||
GET_BOOK_FILE_SEGMENT = 14,
|
||||
GET_BOOK_METADATA = 15,
|
||||
GET_BOOK_COUNT = 6,
|
||||
GET_DEVICE_INFORMATION = 3,
|
||||
GET_INITIALIZATION_INFO = 9,
|
||||
SEND_BOOKLISTS = 7,
|
||||
SEND_BOOK = 8,
|
||||
SEND_BOOK_METADATA = 16,
|
||||
SET_CALIBRE_DEVICE_INFO = 1,
|
||||
SET_CALIBRE_DEVICE_NAME = 2,
|
||||
TOTAL_SPACE = 4,
|
||||
},
|
||||
calibre = nil, -- hash
|
||||
}
|
||||
|
||||
function CalibreWireless:init()
|
||||
self.calibre = {}
|
||||
-- reversed operator codes and names dictionary
|
||||
self.opnames = {}
|
||||
for name, code in pairs(self.opcodes) do
|
||||
self.opnames[code] = name
|
||||
end
|
||||
end
|
||||
|
||||
function CalibreWireless:find_calibre_server()
|
||||
local function find_calibre_server()
|
||||
local socket = require("socket")
|
||||
local udp = socket.udp4()
|
||||
udp:setoption("broadcast", true)
|
||||
udp:setsockname("*", 8134)
|
||||
udp:setsockname("*", COMPANION_PORT)
|
||||
udp:settimeout(3)
|
||||
for _, port in ipairs(self.broadcast_ports) do
|
||||
for _, port in ipairs(BROADCAST_PORTS) do
|
||||
-- broadcast anything to calibre ports and listen to the reply
|
||||
local _, err = udp:sendto("hello", "255.255.255.255", port)
|
||||
if not err then
|
||||
@@ -109,58 +131,39 @@ function CalibreWireless:find_calibre_server()
|
||||
-- replied diagram has greet message from calibre and calibre hostname
|
||||
-- calibre opds port and calibre socket port we will later connect to
|
||||
local _, _, replied_port = dgram:match("calibre wireless device client %(on (.-)%);(%d+),(%d+)$")
|
||||
udp:close()
|
||||
return host, replied_port
|
||||
end
|
||||
end
|
||||
end
|
||||
udp:close()
|
||||
end
|
||||
|
||||
function CalibreWireless:checkCalibreServer(host, port)
|
||||
local function check_host_port(host, port)
|
||||
local socket = require("socket")
|
||||
-- luacheck: ignore 311
|
||||
local ok, err = socket.dns.getaddrinfo(host)
|
||||
if not ok then
|
||||
return false, "host not found"
|
||||
end
|
||||
local ip = ok[1].addr
|
||||
local tcp = socket.tcp()
|
||||
tcp:settimeout(5)
|
||||
-- In case of error, the method returns nil followed by a string describing the error. In case of success, the method returns 1.
|
||||
local ok, err = tcp:connect(host, port)
|
||||
if ok then
|
||||
tcp:close()
|
||||
return true
|
||||
end
|
||||
return false, err
|
||||
-- In case of error, the method returns nil followed by a string
|
||||
-- describing the error. In case of success, the method returns 1.
|
||||
ok, err = tcp:connect(ip, port)
|
||||
tcp:close()
|
||||
return ok, err
|
||||
end
|
||||
|
||||
-- Standard JSON/control opcodes receive callback
|
||||
function CalibreWireless:JSONReceiveCallback(host, port)
|
||||
function CalibreWireless:JSONReceiveCallback()
|
||||
-- NOTE: Closure trickery because we need a reference to *this* self *inside* the callback,
|
||||
-- which will be called as a function from another object (namely, StreamMessageQueue).
|
||||
local this = self
|
||||
return function(t)
|
||||
local data = table.concat(t)
|
||||
this:onReceiveJSON(data)
|
||||
if not this.connect_message then
|
||||
this.password_check_callback = function()
|
||||
local msg
|
||||
if this.invalid_password then
|
||||
msg = _("Invalid password")
|
||||
this.invalid_password = nil
|
||||
this:disconnect()
|
||||
logger.warn("invalid password, disconnecting")
|
||||
elseif this.disconnected_by_server then
|
||||
msg = _("Disconnected by calibre")
|
||||
this.disconnected_by_server = nil
|
||||
logger.info("disconnected by calibre")
|
||||
else
|
||||
msg = T(_("Connected to calibre server at %1"),
|
||||
BD.ltr(T("%1:%2", this.calibre_socket.host, this.calibre_socket.port)))
|
||||
logger.info("connected successfully")
|
||||
end
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = msg,
|
||||
timeout = 2,
|
||||
})
|
||||
end
|
||||
this.connect_message = true
|
||||
UIManager:scheduleIn(1, this.password_check_callback)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -173,20 +176,16 @@ function CalibreWireless:initCalibreMQ(host, port)
|
||||
receiveCallback = self:JSONReceiveCallback(),
|
||||
}
|
||||
self.calibre_socket:start()
|
||||
self.calibre_messagequeue = UIManager:insertZMQ(self.calibre_socket)
|
||||
UIManager:insertZMQ(self.calibre_socket)
|
||||
end
|
||||
logger.info(string.format("connecting to calibre @ %s:%s", host, port))
|
||||
end
|
||||
|
||||
-- will callback initCalibreMQ if inbox is confirmed to be set
|
||||
function CalibreWireless:setInboxDir(host, port)
|
||||
local function set_inbox_dir(cb)
|
||||
local force_chooser_dir
|
||||
if Device:isAndroid() then
|
||||
force_chooser_dir = Device.home_dir
|
||||
end
|
||||
|
||||
local calibre_device = self
|
||||
|
||||
require("ui/downloadmgr"):new{
|
||||
onConfirm = function(inbox)
|
||||
local driver = CalibreMetadata:getDeviceInfo(inbox, "device_name")
|
||||
@@ -194,13 +193,10 @@ function CalibreWireless:setInboxDir(host, port)
|
||||
if not driver then return end
|
||||
return not driver:lower():match("koreader") and not driver:lower():match("folder")
|
||||
end
|
||||
local save_and_resume = function()
|
||||
local save_and_cb = function()
|
||||
logger.info("set inbox directory", inbox)
|
||||
G_reader_settings:saveSetting("inbox_dir", inbox)
|
||||
if host and port then
|
||||
CalibreMetadata:init(inbox)
|
||||
calibre_device:initCalibreMQ(host, port)
|
||||
end
|
||||
cb(inbox)
|
||||
end
|
||||
-- probably not a good idea to mix calibre drivers because
|
||||
-- their default settings usually don't match (lpath et al)
|
||||
@@ -213,74 +209,169 @@ Mixing calibre libraries is not recommended unless you know what you're doing.
|
||||
Do you want to continue? ]]), driver),
|
||||
|
||||
ok_text = _("Continue"),
|
||||
ok_callback = function()
|
||||
save_and_resume()
|
||||
end,
|
||||
ok_callback = save_and_cb
|
||||
})
|
||||
else
|
||||
save_and_resume()
|
||||
save_and_cb()
|
||||
end
|
||||
end,
|
||||
}:chooseDir(force_chooser_dir)
|
||||
end
|
||||
|
||||
function CalibreWireless:connect()
|
||||
if NetworkMgr:willRerunWhenConnected(function() self:connect() end) then
|
||||
if self.calibre_socket ~= nil then
|
||||
return
|
||||
end
|
||||
|
||||
self.connect_message = false
|
||||
local address_type, host, port, ok, err
|
||||
if G_reader_settings:hasNot("calibre_wireless_url") then
|
||||
host, port = self:find_calibre_server()
|
||||
if host and port then
|
||||
address_type = "discovered"
|
||||
else
|
||||
ok = false
|
||||
err = _("Couldn't discover a calibre instance on the local network")
|
||||
address_type = "unavailable"
|
||||
end
|
||||
else
|
||||
local calibre_url = G_reader_settings:readSetting("calibre_wireless_url")
|
||||
host, port = calibre_url["address"], calibre_url["port"]
|
||||
address_type = "specified"
|
||||
-- Ensure we're running in a coroutine.
|
||||
local co = coroutine.running()
|
||||
if not co then
|
||||
Trapper:wrap(function() self:connect() end)
|
||||
return
|
||||
end
|
||||
local re = function(res) coroutine.resume(co, res) end
|
||||
|
||||
-- Setup inbox directory.
|
||||
local inbox_dir = G_reader_settings:readSetting("inbox_dir")
|
||||
if not inbox_dir then
|
||||
set_inbox_dir(re)
|
||||
inbox_dir = coroutine.yield()
|
||||
end
|
||||
|
||||
if host and port then
|
||||
ok, err = self:checkCalibreServer(host, port)
|
||||
-- Ensure network is online.
|
||||
if NetworkMgr:willRerunWhenConnected(self.re) then
|
||||
coroutine.yield()
|
||||
if not NetworkMgr:isConnected() then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local address_type, host, port, ok, err
|
||||
|
||||
-- Setup server address.
|
||||
local calibre_url = G_reader_settings:readSetting("calibre_wireless_url")
|
||||
if calibre_url then
|
||||
host, port = calibre_url["address"], calibre_url["port"]
|
||||
address_type = "specified"
|
||||
ok = true
|
||||
else
|
||||
logger.info("calibre: searching for a server")
|
||||
Trapper:info(_("Searching for a calibre server… (tap to cancel)"))
|
||||
ok, host, port = Trapper:dismissableRunInSubprocess(find_calibre_server)
|
||||
if not ok then
|
||||
-- Canceled.
|
||||
return
|
||||
end
|
||||
if not host or not port then
|
||||
Trapper:info(_("Couldn't discover a calibre instance on the local network"))
|
||||
return
|
||||
end
|
||||
address_type = "discovered"
|
||||
end
|
||||
|
||||
local server_info = BD.ltr(T("%1:%2", host, port))
|
||||
|
||||
-- Yield for `timeout` seconds, return:
|
||||
-- - `true` if resumed because of some server activity
|
||||
-- - `false` on abort / cancelation / disconnection
|
||||
-- - `nil` on timeout
|
||||
local resume_in = function(timeout)
|
||||
UIManager:scheduleIn(timeout, re)
|
||||
local result = coroutine.yield()
|
||||
UIManager:unschedule(re)
|
||||
return result
|
||||
end
|
||||
|
||||
if ok then
|
||||
-- Start connection.
|
||||
logger.info(string.format("calibre: connecting to %s:%s (%s)", host, port, address_type))
|
||||
-- @translators %1: address (host:port), %2: address type (discovered, specified, unavailable)
|
||||
Trapper:info(T(_("Connecting to calibre server at %1 (%2, tap to cancel)"), server_info, _(address_type)))
|
||||
self.re = re
|
||||
self.invalid_password = false
|
||||
self.disconnected_by_server = false
|
||||
if pcall(self.initCalibreMQ, self, host, port) then
|
||||
CalibreMetadata:init(inbox_dir)
|
||||
-- And wait for initial requests: GET_INITIALIZATION_INFO, followed by
|
||||
-- GET_DEVICE_INFORMATION (or a specific DISPLAY_MESSAGE on password error).
|
||||
for _, timeout in ipairs{5, 1} do
|
||||
ok = resume_in(timeout)
|
||||
if not ok then
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
ok = nil
|
||||
end
|
||||
if ok == false then
|
||||
-- Connection was canceled by the user.
|
||||
self:disconnect(true)
|
||||
return
|
||||
end
|
||||
if self.invalid_password then
|
||||
ok, err = false, "invalid password"
|
||||
elseif not ok then
|
||||
-- Manually open a TCP connection to get a more informative error.
|
||||
ok, err = check_host_port(host, port)
|
||||
if ok then
|
||||
ok, err = false, "handshake timeout"
|
||||
else
|
||||
err = err:lower()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not ok then
|
||||
host = host or "????"
|
||||
port = port or "??"
|
||||
err = err or _("N/A")
|
||||
logger.warn(string.format("Cannot connect to %s calibre server at %s:%s (%s)", address_type, host, port, err))
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = T(_("Cannot connect to calibre server at %1 (%2)"),
|
||||
BD.ltr(T("%1:%2", host, port)), err)
|
||||
})
|
||||
else
|
||||
local inbox_dir = G_reader_settings:readSetting("inbox_dir")
|
||||
if inbox_dir then
|
||||
CalibreMetadata:init(inbox_dir)
|
||||
self:initCalibreMQ(host, port)
|
||||
else
|
||||
self:setInboxDir(host, port)
|
||||
end
|
||||
logger.warn("calibre: connection failed,", err)
|
||||
-- @translators %1: address (host:port), %2: error
|
||||
Trapper:info(T(_("Cannot connect to calibre server at %1 (%2)"), server_info, _(err)))
|
||||
self:disconnect(not self.invalid_password)
|
||||
return
|
||||
end
|
||||
|
||||
Trapper:clear()
|
||||
|
||||
logger.info("calibre: connected")
|
||||
|
||||
-- Heartbeat monitoring…
|
||||
while ok and not self.disconnected_by_server do
|
||||
ok = resume_in(15)
|
||||
end
|
||||
|
||||
local msg
|
||||
if self.disconnected_by_server then
|
||||
logger.info("disconnected by calibre")
|
||||
msg = _("Disconnected by calibre")
|
||||
elseif ok == nil then
|
||||
logger.info("calibre: no activity")
|
||||
msg = _("Disconnected from calibre (no activity)")
|
||||
end
|
||||
if msg then
|
||||
UIManager:show(InfoMessage:new{ text = msg, timeout = 2 })
|
||||
self:disconnect(not self.disconnected_by_server)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function CalibreWireless:disconnect()
|
||||
logger.info("disconnecting from calibre")
|
||||
self.connect_message = false
|
||||
if self.calibre_socket then
|
||||
self.calibre_socket:stop()
|
||||
self.calibre_socket = nil
|
||||
function CalibreWireless:disconnect(no_parting_noop)
|
||||
if self.calibre_socket == nil then
|
||||
return
|
||||
end
|
||||
if self.calibre_messagequeue then
|
||||
UIManager:removeZMQ(self.calibre_messagequeue)
|
||||
self.calibre_messagequeue = nil
|
||||
logger.info("calibre: disconnecting")
|
||||
|
||||
self.re(false)
|
||||
self.re = nil
|
||||
|
||||
if not no_parting_noop then
|
||||
self:sendJsonData('NOOP', {})
|
||||
end
|
||||
|
||||
UIManager:removeZMQ(self.calibre_socket)
|
||||
self.calibre_socket:stop()
|
||||
self.calibre_socket = nil
|
||||
self.invalid_password = false
|
||||
self.disconnected_by_server = false
|
||||
|
||||
CalibreMetadata:clean()
|
||||
|
||||
-- Assume the library content was modified, as such, invalidate our Search metadata cache.
|
||||
@@ -302,7 +393,7 @@ function CalibreWireless:onReceiveJSON(data)
|
||||
-- 34[0, {"key0":value, "key1": value}]
|
||||
-- the JSON string has a leading length string field followed by the actual
|
||||
-- JSON data in which the first element is always the operator code which can
|
||||
-- be looked up in the opnames dictionary
|
||||
-- be looked up in the opcodes dictionary
|
||||
while self.buffer ~= nil do
|
||||
--logger.info("buffer", self.buffer)
|
||||
local index = self.buffer:find('%[') or 1
|
||||
@@ -323,29 +414,30 @@ function CalibreWireless:onReceiveJSON(data)
|
||||
--logger.dbg("received json table", json)
|
||||
local opcode = json[1]
|
||||
local arg = json[2]
|
||||
if self.opnames[opcode] == 'GET_INITIALIZATION_INFO' then
|
||||
if opcode == OPCODES.GET_INITIALIZATION_INFO then
|
||||
self:getInitInfo(arg)
|
||||
elseif self.opnames[opcode] == 'GET_DEVICE_INFORMATION' then
|
||||
elseif opcode == OPCODES.GET_DEVICE_INFORMATION then
|
||||
self:getDeviceInfo(arg)
|
||||
elseif self.opnames[opcode] == 'SET_CALIBRE_DEVICE_INFO' then
|
||||
elseif opcode == OPCODES.SET_CALIBRE_DEVICE_INFO then
|
||||
self:setCalibreInfo(arg)
|
||||
elseif self.opnames[opcode] == 'FREE_SPACE' then
|
||||
elseif opcode == OPCODES.FREE_SPACE then
|
||||
self:getFreeSpace(arg)
|
||||
elseif self.opnames[opcode] == 'SET_LIBRARY_INFO' then
|
||||
elseif opcode == OPCODES.SET_LIBRARY_INFO then
|
||||
self:setLibraryInfo(arg)
|
||||
elseif self.opnames[opcode] == 'GET_BOOK_COUNT' then
|
||||
elseif opcode == OPCODES.GET_BOOK_COUNT then
|
||||
self:getBookCount(arg)
|
||||
elseif self.opnames[opcode] == 'SEND_BOOK' then
|
||||
elseif opcode == OPCODES.SEND_BOOK then
|
||||
self:sendBook(arg)
|
||||
elseif self.opnames[opcode] == 'DELETE_BOOK' then
|
||||
elseif opcode == OPCODES.DELETE_BOOK then
|
||||
self:deleteBook(arg)
|
||||
elseif self.opnames[opcode] == 'GET_BOOK_FILE_SEGMENT' then
|
||||
elseif opcode == OPCODES.GET_BOOK_FILE_SEGMENT then
|
||||
self:sendToCalibre(arg)
|
||||
elseif self.opnames[opcode] == 'DISPLAY_MESSAGE' then
|
||||
elseif opcode == OPCODES.DISPLAY_MESSAGE then
|
||||
self:serverFeedback(arg)
|
||||
elseif self.opnames[opcode] == 'NOOP' then
|
||||
elseif opcode == OPCODES.NOOP then
|
||||
self:noop(arg)
|
||||
end
|
||||
self.re(true)
|
||||
else
|
||||
logger.warn("failed to decode json data", err)
|
||||
end
|
||||
@@ -353,7 +445,7 @@ function CalibreWireless:onReceiveJSON(data)
|
||||
end
|
||||
|
||||
function CalibreWireless:sendJsonData(opname, data)
|
||||
local json, err = rapidjson.encode(rapidjson.array({self.opcodes[opname], data}))
|
||||
local json, err = rapidjson.encode(rapidjson.array({OPCODES[opname], data}))
|
||||
if json then
|
||||
-- length of json data should be before the real json data
|
||||
self.calibre_socket:send(tostring(#json)..json)
|
||||
@@ -499,7 +591,6 @@ function CalibreWireless:noop(arg)
|
||||
if arg.ejecting then
|
||||
self:sendJsonData('OK', {})
|
||||
self.disconnected_by_server = true
|
||||
self:disconnect()
|
||||
return
|
||||
end
|
||||
-- calibre announces the count of books that need more metadata
|
||||
@@ -585,13 +676,12 @@ function CalibreWireless:sendBook(arg)
|
||||
calibre_device.buffer = data:sub(#to_write_data + 1) or ""
|
||||
--logger.info("device buffer", calibre_device.buffer)
|
||||
if calibre_device.buffer ~= "" then
|
||||
UIManager:scheduleIn(0.1, function()
|
||||
-- since data is already copied to buffer
|
||||
-- onReceiveJSON parameter should be nil
|
||||
calibre_device:onReceiveJSON()
|
||||
end)
|
||||
-- since data is already copied to buffer
|
||||
-- onReceiveJSON parameter should be nil
|
||||
calibre_device:onReceiveJSON()
|
||||
end
|
||||
end
|
||||
self.re(true)
|
||||
end
|
||||
self:sendJsonData('OK', {})
|
||||
-- end of the batch
|
||||
|
||||
Reference in New Issue
Block a user