but forgot what it's like
Posts: 741
Karma: 2345678
Join Date: Dec 2011
Location: north (by northwest)
Device: Kindle Touch
|
Quote:
Originally Posted by nick-tech
Thank you NiJuLe for your quick response. It's almost what I want, but i'd like to see the charge/discharge rate permanently in the status bar, just like the charge percentage. Is there a way to get that working?
|
Here are three files.
/etc/init/battery_current_indicator.confSpoiler:
Code:
# Copyright © 2015 eureka
#
# 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.
start on started pillow
stop on stopping pillow
pre-start script
# Wait for pillow on 'started pillow' event.
if [ "x${JOB}" == "xpillow" -a "x${UPSTART_EVENTS}" == "xstarted" ]; then
lipc-wait-event com.lab126.pillow stateChange
sleep 2
fi
end script
post-start exec /bin/sh /var/local/battery_current/battery_current_indicator.sh enable
pre-stop exec /bin/sh /var/local/battery_current/battery_current_indicator.sh disable
exec /usr/bin/lua /var/local/battery_current/battery_current_lipc_publisher.lua
/var/local/battery_current/battery_current_indicator.shSpoiler:
Code:
#!/bin/sh
# Copyright © 2015 eureka
#
# 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.
# Format given standard input (remove newlines and escape double quotes)
# for using it in JSON message passed to lipc-set-prop.
format_js_script () {
local line
local js_script
while IFS="" read -r line; do js_script="${js_script}${line}"; done
echo "${js_script}" | sed -e 's,",\\",g'
}
[ "x${1}" = "xdisable" ] && ENABLE_INDICATOR=false || ENABLE_INDICATOR=true
# Construct JavaScript code executed in context of Pillow container.
# It's glued into one big line (newlines are removed), so syntax semicolons
# are required and any comments must be block comments (not line comments).
SCRIPT=`format_js_script << 'JAVASCRIPT' \
| sed -e "s/__ENABLE_INDICATOR__/${ENABLE_INDICATOR}/"
/* JavaScript code begins here. */
(function () {
var _enableIndicator = __ENABLE_INDICATOR__,
_originalEventsCallback = StatusBar && StatusBar.eventsCallback,
_batteryIconId = BatteryState.batteryIconDiv,
_batteryIconEl = _batteryIconId
&& document.getElementById(_batteryIconId),
_batteryCurrentId = "batteryCurrent",
_batteryCurrentEl = document.getElementById(_batteryCurrentId);
/* Stock battery icon element not found or LIPC events handler function is
* not defined under expected name, return immediately. */
if (!_batteryIconEl || !_originalEventsCallback) {
return;
}
/* Custom element displaying battery current already present in DOM.
* Either return early if disabling was not requested or execute
* disabling procedures and then return.
*/
if (_batteryCurrentEl !== null) {
if (_enableIndicator) {
return;
}
_batteryCurrentEl.parentNode.removeChild(_batteryCurrentEl);
return;
}
/* Setup element for displaying battery current. */
_batteryCurrentEl = document.createElement("div");
_batteryCurrentEl.id = _batteryCurrentId;
_batteryCurrentEl.style.paddingTop = "2pt";
_batteryCurrentEl.style.paddingRight = "3pt";
_batteryCurrentEl.textContent = "_ mA";
/* It is not possible to unsubscribe from LIPC event in Pillow container
* (or, at least, I did not find a way to do it).
*
* Here part of event handler is attached to 'window' object. It is
* persisted between disabling and enabling indicator and shows that
* subscribing was already done.
*/
if (typeof window.__updateBatteryCurrent__ !== "function") {
window.__updateBatteryCurrent__ = function (batteryCurrentValue) {
var batteryCurrentEl = document.getElementById(_batteryCurrentId);
if (batteryCurrentEl === null) {
/* Indicator was disabled. */
return;
}
batteryCurrentEl.textContent =
batteryCurrentValue
? (batteryCurrentValue + " mA")
: "? ma";
};
StatusBar.eventsCallback = function (eventDataJson) {
var eventData = JSON.parse(eventDataJson),
eventSrcOk =
eventData
&& (eventData.eventSrc === "com.example.batterycurrent"),
eventNameOk =
eventData
&& (eventData.eventName === "currentChanged"),
eventValues = eventData && eventData.eventValues;
if (eventSrcOk && eventNameOk && eventValues) {
window.__updateBatteryCurrent__(eventValues[0]);
}
_originalEventsCallback(eventDataJson);
};
nativeBridge.registerEventsWatchCallback(StatusBar.eventsCallback);
nativeBridge.subscribeToEvent(
"com.example.batterycurrent",
"currentChanged"
);
}
/* Insert battery current element left of stock battery icon. */
_batteryIconEl.parentNode.insertBefore(_batteryCurrentEl, _batteryIconEl);
/* Get initial battery current value and display it. */
window.__updateBatteryCurrent__(nativeBridge.getIntLipcProperty(
"com.example.batterycurrent",
"ma"
));
})();
/* JavaScript code ends here. */
`
MESSAGE='{
"pillowId": "default_status_bar",
"function": "'${SCRIPT}'"
}'
lipc-set-prop -s com.lab126.pillow interrogatePillow "${MESSAGE}"
/var/local/battery_current/battery_current_lipc_publisher.luaSpoiler:
Code:
#!/usr/bin/lua
-- Copyright © 2015 eureka
--
-- 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.
require("liblipclua")
------------------------------------------------------------------------------
-- Configuration
------------------------------------------------------------------------------
-- Script registers itself as a LIPC publisher under this name.
local LIPC_PUBLISHER_NAME = "com.example.batterycurrent"
-- Battery current will be exported through this LIPC int property.
local LIPC_PROPERTY_NAME = "ma"
-- Changed battery current value is broadcasted by script as a LIPC event with
-- this name.
-- (Set it to nil to disable event sending.)
local LIPC_EVENT_NAME = "currentChanged"
-- Glob pattern of path to file with data of battery current.
--
-- Part of data file path is changed between device models, so real path
-- is found in runtime by glob pattern.
local DATA_FILE_GLOB = "/sys/devices/system/*_battery/*_battery0/battery_current"
-- Time period between re-reading data from data file.
local DATA_REFRESH_PERIOD = 1 -- second(s)
------------------------------------------------------------------------------
-- Supporting functions
------------------------------------------------------------------------------
local function exit_with_message(exit_code, message)
io.stderr:write(message .. "\n")
io.stderr:flush()
os.exit(exit_code)
end
-- Call 'ls' command with passed glob pattern and return found path to file.
local function find_file_path (file_glob)
local cmd = "ls " .. file_glob
local output, err_message = io.popen(cmd, "r")
if output == nil then
error(err_message)
end
local file_path = output:read()
output:close()
if file_path == nil then
error("Can't read output of '" .. cmd .. "'")
elseif file_path:sub(1, 4) == "ls: " then
error("Can't find file by glob pattern '" .. file_glob .. "'")
end
return file_path
end
-- Return battery current value read from first file line.
local function read_current_from_file (file_path)
local file, err_message = io.open(file_path)
if file == nil then
error(err_message)
end
local result = file:read("*n")
file:close()
if result == nil then
error("Can't read number from file '" .. file_path .. "'")
end
return result
end
------------------------------------------------------------------------------
-- Program setup
------------------------------------------------------------------------------
local data_file_found, data_file_path = pcall(find_file_path, DATA_FILE_GLOB)
if not data_file_found then
exit_with_message(1, data_file_path)
end
local lipc_handle, lipc_err_msg, lipc_err_num = lipc.init(LIPC_PUBLISHER_NAME)
if not lipc_handle then
exit_wit_message(
lipc_err_num,
"Failed to initialize LIPC: ("
.. tostring(lipc_err_num) .. ") "
.. lipc_err_msg)
else
lipc.set_error_handler(function(msg) io.stderr:write(msg .. "\n") end)
end
local ma_property = lipc_handle:register_int_property(LIPC_PROPERTY_NAME, "r")
------------------------------------------------------------------------------
-- Main loop
------------------------------------------------------------------------------
local ma_value_read_ok, ma_value, prev_ma_value
while true do
-- Read battery current value.
ma_value_read_ok, ma_value = pcall(read_current_from_file, data_file_path)
if not ma_value_read_ok then
lipc_handle:close()
exit_with_message(1, ma_value)
end
-- Set LIPC property value.
ma_property.value = ma_value
-- Send LIPC event when value is changed.
if LIPC_EVENT_NAME ~= nil and ma_value ~= prev_ma_value then
lipc_handle:send_event(LIPC_EVENT_NAME, {ma_value})
prev_ma_value = ma_value
end
-- Use event loop timeout as a pause duration.
lipc.run_event_loop(DATA_REFRESH_PERIOD)
end
lipc_handle:close()
Put them on their paths. Then indicator could be enabled with start battery_current_indicator or disabled with stop battery_current_indicator. It will also be enabled automatically on pillow (re)start (i.e. on reboot too).
Battery current will be displayed as 78 mA or -98 mA left of stock battery icon in status bar. Sysfs value will be continuously polled in intervals of 1 second and status bar indicator will be refreshed on value change.
It was tested on Kindle Touch 5.3.7.2.
Last edited by eureka; 06-11-2015 at 01:33 AM.
Reason: sysfs value isn't watched in realtime, but polled in small intervals
|