How to read the battery level in Ubuntu? - c++

I've searched for a while on how to do this without any special library or anything, and it took a while to find something that's working properly.
It's possible to use
/sys/class/power_supply/BAT0/subsystem/BAT0/charge_now
/sys/class/power_supply/BAT0/subsystem/BAT0/charge_full
I was wondering, is there a better way to get the battery status using C/C++ in Ubuntu 18.04?

In case this is never answered.. this is my solution:
#define PATH_BATT_CHARGE_NOW "/sys/class/power_supply/BAT0/subsystem/BAT0/charge_now"
#define PATH_BATT_CHARGE_FULL "/sys/class/power_supply/BAT0/subsystem/BAT0/charge_full"
int getBattState(void)
{
int chargedPercent = 0;
FILE *battChargeNow;
FILE *battChargeFull;
long unsigned int battMax_mAh = 0;
long unsigned int battRemain_mAh = 0;
if (NULL == (battChargeNow = fopen(PATH_BATT_CHARGE_NOW, "r")))
{
fclose(battChargeNow);
return -1;
}
if (NULL == (battChargeFull = fopen(PATH_BATT_CHARGE_FULL, "r")))
{
fclose(battChargeNow);
fclose(battChargeFull);
return -1;
}
fscanf((FILE *)battChargeFull, "%lu", &battMax_mAh);
fscanf((FILE *)battChargeNow, "%lu", &battRemain_mAh);
chargedPercent = 100.00 * ((float)battRemain_mAh / (float)battMax_mAh);
return chargedPercent;
}

Related

Could anyone teach me on how to unpack the return value?

below is the code which had writted in c++ and basically what this function do would be pack the value into hex and unpack the return value in hex
abc_API_API long __stdcall ABC_ExecuteCommand(slngCommandParameter *lngCmdPrmCode, shexRespData *hexRespData, sRespData *Data)
{
long lngResult, lngRtn;
char strMsg[512];
memset((void*)strMsg, '\0', sizeof(strMsg));
shexCommandParameter hexCmdPrmCode;
try {
sCmdData cmdData;
PBYTE pbRDTBuff;
PDWORD pcbRDTLength;
PCRSTATUS lpStatus;
MappingTable(&hexCmdPrmCode, lngCmdPrmCode);
sprintf_s(strMsg, "Command : [%X]%s", hexCmdPrmCode.HexCommandCode, hexCmdPrmCode.Command.c_str());
WriteLog(strMsg);
sprintf_s(strMsg, "Parameter: [%X]%s", hexCmdPrmCode.HexParameterCode, hexCmdPrmCode.Parameter.c_str());
WriteLog(strMsg);
cmdData.bCMDByte1 = 'C';
cmdData.bCMDByte2 = 'D';
char *lpCMPBuff = new char[lngCmdPrmCode->lngDataSize + 1];
lpCMPBuff[(lngCmdPrmCode->lngDataSize)] = '\0';
cmdData.cbCMPLength = USHORT(lngCmdPrmCode->lngDataSize);
if (lngCmdPrmCode->lngDataSize > 0)
PackBCDHex(lpCMPBuff, strRemoveSpace(lngCmdPrmCode->strData), (lngCmdPrmCode->lngDataSize) * 2);
cmdData.pbCMPBuff = LPBYTE(lpCMPBuff);
lngResult = F3_ExecCommand (g_Reader, cmdData.bCMDByte1, cmdData.bCMDByte2 , cmdData.pbCMPBuff, cmdData.cbCMPLength, pbRDTBuff, pcbRDTLength, lpStatus);
if(lngResult == F3_S_SUCCESS) {
lngRtn = 0;
} else {
lngRtn = -1;
}
Data->ErrCode = (long)lngResult;
Data->Message = SysAllocStringByteLen(strMsg, strlen(strMsg));
WriteLog(strMsg);
return lngRtn;
} catch (exception& e) {
sprintf_s(strMsg, "Exception#ABC_DeniedInsertion: %s", e.what());
WriteError(strMsg);
return -1;
}
}
but i had no clue on how to properly unpack the data which suppose to put in this line
if(lngResult == F3_S_SUCCESS) {
lngRtn = 0;
} else {
lngRtn = -1;
}
below would the the unpack function which would be used
UnpackBCDHex
what i know is when lngResult is equal to 0 which means success, then the pbRDTBuff would point to the buff of the response data,and when pcbRDTLength >0 then i would need to assign an array and put the data in and using UnpackBCDHex to unpack it. but i have no clue on how can i achieve it. can anyone can guide me or showing me which document i can refer to finish this function?
thank you
HI, The problem had been solved. Thank you for all the help.Really really appreciate for those who willing spend their time and inbox chating with me teaching me step by step and trying to help me figure out the issue together.I really love this community which is such beginner friendly.Love u all 3000 haha

Pass Byte Array as std::vector<char> from Node.js to C++ Addon

I have some constraints where the addon is built with nan.h and v8 (not the new node-addon-api).
The end function is a part of a library. It accepts std::vector<char> that represents the bytes of an image.
I tried creating an image buffer from Node.js:
const img = fs.readFileSync('./myImage.png');
myAddonFunction(Buffer.from(img));
I am not really sure how to continue from here. I tried creating a new vector with a buffer, like so:
std::vector<char> buffer(data);
But it seems like I need to give it a size, which I am unsure how to get. Regardless, even when I use the initial buffer size (from Node.js), the image fails to go through.
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
[1] 16021 abort (core dumped)
However, when I read the image directly from C++, it all works fine:
std::ifstream ifs ("./myImage.png", std::ios::binary|std::ios::ate);
std::ifstream::pos_type pos = ifs.tellg();
std::vector<char> buffer(pos);
ifs.seekg(0, std::ios::beg);
ifs.read(&buffer[0], pos);
// further below, I pass "buffer" to the function and it works just fine.
But of course, I need the image to come from Node.js. Maybe Buffer is not what I am looking for?
Here is an example based on N-API; I would also encourage you to take a look similar implementation based on node-addon-api (it is an easy to use C++ wrapper on top of N-API)
https://github.com/nodejs/node-addon-examples/tree/master/array_buffer_to_native/node-addon-api
#include <assert.h>
#include "addon_api.h"
#include "stdio.h"
napi_value CArrayBuffSum(napi_env env, napi_callback_info info)
{
napi_status status;
const size_t MaxArgExpected = 1;
napi_value args[MaxArgExpected];
size_t argc = sizeof(args) / sizeof(napi_value);
status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
assert(status == napi_ok);
if (argc < 1)
napi_throw_error(env, "EINVAL", "Too few arguments");
napi_value buff = args[0];
napi_valuetype valuetype;
status = napi_typeof(env, buff, &valuetype);
assert(status == napi_ok);
if (valuetype == napi_object)
{
bool isArrayBuff = 0;
status = napi_is_arraybuffer(env, buff, &isArrayBuff);
assert(status == napi_ok);
if (isArrayBuff != true)
napi_throw_error(env, "EINVAL", "Expected an ArrayBuffer");
}
int32_t *buff_data = NULL;
size_t byte_length = 0;
int32_t sum = 0;
napi_get_arraybuffer_info(env, buff, (void **)&buff_data, &byte_length);
assert(status == napi_ok);
printf("\nC: Int32Array size = %d, (ie: bytes=%d)",
(int)(byte_length / sizeof(int32_t)), (int)byte_length);
for (int i = 0; i < byte_length / sizeof(int32_t); ++i)
{
sum += *(buff_data + i);
printf("\nC: Int32ArrayBuff[%d] = %d", i, *(buff_data + i));
}
napi_value rcValue;
napi_create_int32(env, sum, &rcValue);
return (rcValue);
}
The JavaScript code to call the addon
'use strict'
const myaddon = require('bindings')('mync1');
function test1() {
const array = new Int32Array(10);
for (let i = 0; i < 10; ++i)
array[i] = i * 5;
const sum = myaddon.ArrayBuffSum(array.buffer);
console.log();
console.log(`js: Sum of the array = ${sum}`);
}
test1();
The Output of the code execution:
C: Int32Array size = 10, (ie: bytes=40)
C: Int32ArrayBuff[0] = 0
C: Int32ArrayBuff[1] = 5
C: Int32ArrayBuff[2] = 10
C: Int32ArrayBuff[3] = 15
C: Int32ArrayBuff[4] = 20
C: Int32ArrayBuff[5] = 25
C: Int32ArrayBuff[6] = 30
C: Int32ArrayBuff[7] = 35
C: Int32ArrayBuff[8] = 40
C: Int32ArrayBuff[9] = 45
js: Sum of the array = 225

SoundTouch library messes up the ending when pitch-shifting

I'm using the SoundTouch library to pitch-shift some audio files. Everything works well, except the last few hundred milliseconds of the new audio file are not like the original file. Here is the original file:
And here's what I get after pitch-shifting:
As you can see the ending is not right. It's like there was nothing there in the original file, when there certainly is.
Here's the code I'm using:
int generateFile(WavInFile *file, SoundTouch *st, string fileName, int semitones)
{
const bool speech = true;
SAMPLETYPE samples[BUFF_SIZE];
WavOutFile *out = new WavOutFile(fileName.c_str(), (int)file->getSampleRate(), (int)file->getNumBits(), (int)file->getNumChannels());
int nChannels = (int)file->getNumChannels();
assert(nChannels > 0);
int num, nSamples;
int buffSizeSamples = BUFF_SIZE / nChannels;
st->setSampleRate((int)file->getSampleRate());
st->setChannels(nChannels);
st->setPitchSemiTones(semitones);
if (!speech)
{
st->setSetting(SETTING_USE_QUICKSEEK, 0);
st->setSetting(SETTING_USE_AA_FILTER, 0);
}
else
{
st->setSetting(SETTING_USE_QUICKSEEK, 0);
st->setSetting(SETTING_SEQUENCE_MS, 40);
st->setSetting(SETTING_SEEKWINDOW_MS, 15);
st->setSetting(SETTING_OVERLAP_MS, 8);
}
while (file->eof() == 0)
{
num = file->read(samples, BUFF_SIZE);
nSamples = num / (int)file->getNumChannels();
st->putSamples(samples, nSamples);
do
{
nSamples = st->receiveSamples(samples, buffSizeSamples);
out->write(samples, nSamples * nChannels);
} while (nSamples != 0);
}
st->flush();
do
{
nSamples = st->receiveSamples(samples, buffSizeSamples);
out->write(samples, nSamples * nChannels);
} while (nSamples != 0);
delete out;
return 0;
}
And yes, I delete WavInFile *file later in my code. So my question is- Why is SoundTouch doing this and how can I fix it?
Also I cannot simply cut the wrong part of the new audio file because I'm generating hundreds of files this way so cutting every single one of them would be...

How to find out the next time when the clock will be adjusted for Daylight Saving?

I'm curious, if there's any way to find out the UTC date/time when the next Daylight Saving adjustment will take place?
Something akin to what Windows reports (see circled):
This information is provided in Windows by the EnumDynamicTimeZoneInformation function.
See http://msdn.microsoft.com/en-us/library/windows/desktop/hh706893%28v=vs.85%29.aspx
There is a database that has code and data: http://www.iana.org/time-zones
I don't think there's a specific API for this. I would just do a binary search, using localtime (and maybe time and mktime) from <ctime> (C++) or <time.h> (C).
A basic approach is to scan ahead three months at a time until the tm_isdst flag in the returned data structure is flipped. Then you can start binary searching between the last two two dates to figure out exactly when it flips.
See http://www.cplusplus.com/reference/ctime/tm/ for reference material.
I appreciate all your replies. And, yes, indeed I was asking about a WinAPI for Windows.
I did more research and came up with the following method that does what I wanted. It uses C++ and MFC's COleDateTime for easier date/time calculations. Other than that it's just C++ and WinAPIs. Please check if I understood the documentation for the DYNAMIC_TIME_ZONE_INFORMATION correctly. Here's the code:
int GetNextDaylightSavingAdjustmentTime(SYSTEMTIME* pOutDtNextDST_Local, int* pnOutAdjustmentMin)
{
//Get next time when DST adjustment will take place
//'pOutDtNextDST_Local' = if not NULL, receives the (local) time when next DST adjustment will take place
//'pnOutAdjustmentMin' = if not NULL, receives the amount of adjustment in minutes
//RETURN:
// = 1 if got the time, or
// = 0 if DST is not used
// = -1 if error (check GetLastError() for info)
int nOSError = NO_ERROR;
//Load API dynamically (in case of Windows XP)
BOOL (WINAPI *pfnGetDynamicTimeZoneInformation)(PDYNAMIC_TIME_ZONE_INFORMATION);
(FARPROC&)pfnGetDynamicTimeZoneInformation =
::GetProcAddress(::GetModuleHandle(L"Kernel32.dll"), "GetDynamicTimeZoneInformation");
DWORD tzID;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
int nBiasDaylight;
//Use newer API if possible
if(pfnGetDynamicTimeZoneInformation)
{
DYNAMIC_TIME_ZONE_INFORMATION dtzi = {0};
tzID = pfnGetDynamicTimeZoneInformation(&dtzi);
StandardDate = dtzi.StandardDate;
DaylightDate = dtzi.DaylightDate;
nBiasDaylight = dtzi.DaylightBias;
}
else
{
//Older API
TIME_ZONE_INFORMATION tzi = {0};
tzID = GetTimeZoneInformation(&tzi);
StandardDate = tzi.StandardDate;
DaylightDate = tzi.DaylightDate;
nBiasDaylight = tzi.DaylightBias;
}
int nRes = -1;
int nAdjMins = 0;
SYSTEMTIME stDstChange;
memset(&stDstChange, 0, sizeof(stDstChange));
SYSTEMTIME stDst;
if(tzID == TIME_ZONE_ID_STANDARD ||
tzID == TIME_ZONE_ID_DAYLIGHT)
{
stDst = tzID != TIME_ZONE_ID_DAYLIGHT ? DaylightDate : StandardDate;
if(stDst.wMonth >= 1 &&
stDst.wMonth <= 12 &&
stDst.wDay >= 1 &&
stDst.wDayOfWeek >= 0 &&
stDst.wDayOfWeek <= 6)
{
//Get adjustment bias
nAdjMins = tzID != TIME_ZONE_ID_DAYLIGHT ? -nBiasDaylight : nBiasDaylight;
if(stDst.wYear == 0)
{
//Relative date
SYSTEMTIME stLocal;
::GetLocalTime(&stLocal);
//Begin from the 1st day of the month &
//make sure that the date is in the future
COleDateTime dt;
for(int nYear = stLocal.wYear;; nYear++)
{
dt.SetDateTime(nYear, stDst.wMonth, 1, stDst.wHour, stDst.wMinute, stDst.wSecond);
if(dt > COleDateTime::GetCurrentTime())
break;
}
int nRequiredWeek = stDst.wDay >= 1 && stDst.wDay <= 5 ? stDst.wDay : 5;
for(int nCntDOW = 1;;)
{
//0=Sunday, 1=Monday; 2=Tuesday; 3=Wednesday; 4=Thursday; 5=Friday; 6=Saturday
int dow = dt.GetDayOfWeek() - 1;
ASSERT(dow >= 0 && dow <= 6);
if(dow == stDst.wDayOfWeek)
{
if(nCntDOW >= nRequiredWeek)
{
//Stop
break;
}
else
{
nCntDOW++;
}
}
//Go to next day
dt += COleDateTimeSpan(1, 0, 0, 0);
}
//Convert back to system time
if(dt.GetAsSystemTime(stDstChange))
{
//Success
nRes = 1;
}
else
{
//Failed
nOSError = ERROR_INVALID_FUNCTION;
ASSERT(NULL);
}
}
else
{
//Absolute date
stDstChange = stDst;
nRes = 1;
}
}
else
{
//Failed
nOSError = ERROR_INVALID_PARAMETER;
ASSERT(NULL);
}
}
else
{
//DST is not used
if(tzID == TIME_ZONE_ID_UNKNOWN)
{
nRes = 0;
}
else
{
//Error
nOSError = ERROR_INVALID_DATA;
ASSERT(NULL);
}
}
if(pOutDtNextDST_Local)
*pOutDtNextDST_Local = stDstChange;
if(pnOutAdjustmentMin)
*pnOutAdjustmentMin = nAdjMins;
::SetLastError(nOSError);
return nRes;
}
PS. And scratch my request for the UTC time. As I learned, it is easier to deal with local time in this situation.

Not able to add certificate policy extension using openssl APIs in c++

I tried using following syntax for the same :
add_ext(x509OutCertificate, NID_certificate_policies, "Policy: 2.16.840.1.113733.1.7.54 ,CPS: https://www.verisign.com/cps");
add_ext(x509OutCertificate, NID_certificate_policies, "2.16.840.1.113733.1.7.54,https://www.verisign.com/cps");
& many more combinations.
but not able to add this extension in certificate. Any clue what is wrong?
Thanks in advance
This is really a comment, but the comment does not have the space.
$ grep -R NID_certificate_policies *crypto/objects/obj_dat.h: NID_certificate_policies,3,&(lvalues[512]),0},
crypto/objects/objects.h:#define NID_certificate_policies 89
crypto/objects/obj_mac.h:#define NID_certificate_policies 89
crypto/x509v3/v3_cpols.c:NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
crypto/x509v3/pcy_cache.c: ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
crypto/x509v3/v3_purp.c: NID_certificate_policies, /* 89 */
Looking at v3_cpols.c, there's an ominous warning:
/* Certificate policies extension support: this one is a bit complex... */
Here's how its declared:
const X509V3_EXT_METHOD v3_cpols = {
NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
0,0,0,0,
0,0,
0,0,
(X509V3_EXT_I2R)i2r_certpol,
(X509V3_EXT_R2I)r2i_certpol,
NULL
};
ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
v3_cpol is then used in ext_dat.h:
static const X509V3_EXT_METHOD *standard_exts[] = {
&v3_nscert,
&v3_ns_ia5_list[0],
&v3_ns_ia5_list[1],
&v3_ns_ia5_list[2],
&v3_ns_ia5_list[3],
&v3_ns_ia5_list[4],
&v3_ns_ia5_list[5],
&v3_ns_ia5_list[6],
...
&v3_cpols,
...
};
There does not appear to be documentation or clear usage. The two books I have on OpenSSL lack a treatment on it. It looks like you are in muddy waters.
Perhaps the folks at the OpenSSL user's list can help out. I suggest it because some folks on the list can probably answer it (SH, DT, VD, etc), but I have not seen them on Stack Overflow's site.
Its been a long time for this question, but i looked into openssl1.0.2k source code, and i found its not support add cps extension directly:
static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, char *value)
{
WriteLogToFile("In r2i_certpol");
STACK_OF(POLICYINFO) *pols = NULL;
char *pstr;
POLICYINFO *pol;
ASN1_OBJECT *pobj;
STACK_OF(CONF_VALUE) *vals;
CONF_VALUE *cnf;
int i, ia5org;
pols = sk_POLICYINFO_new_null();
if (pols == NULL) {
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
return NULL;
}
WriteLogToFile("Before X509V3_parse_list");
vals = X509V3_parse_list(value);
WriteLogToFile("After X509V3_parse_list");
if (vals == NULL) {
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
goto err;
}
ia5org = 0;
for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
cnf = sk_CONF_VALUE_value(vals, i);
if (cnf->value || !cnf->name) {
char str[1000];
sprintf(str, "cnf->value: %s, cnf->name: %s", cnf->value, cnf->name);
WriteLogToFile(str);
X509V3err(X509V3_F_R2I_CERTPOL,
X509V3_R_INVALID_POLICY_IDENTIFIER);
X509V3_conf_err(cnf);
goto err;
}
pstr = cnf->name;
WriteLogToFile(pstr);
if (!strcmp(pstr, "ia5org")) {
ia5org = 1;
continue;
} else if (*pstr == '#') {
STACK_OF(CONF_VALUE) *polsect;
polsect = X509V3_get_section(ctx, pstr + 1);
if (!polsect) {
X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION);
X509V3_conf_err(cnf);
goto err;
}
pol = policy_section(ctx, polsect, ia5org);
X509V3_section_free(ctx, polsect);
if (!pol)
goto err;
} else {
if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
X509V3err(X509V3_F_R2I_CERTPOL,
X509V3_R_INVALID_OBJECT_IDENTIFIER);
X509V3_conf_err(cnf);
goto err;
}
pol = POLICYINFO_new();
if (pol == NULL) {
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
goto err;
}
pol->policyid = pobj;
}
if (!sk_POLICYINFO_push(pols, pol)) {
POLICYINFO_free(pol);
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
return pols;
err:
sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
return NULL;
}
The "CPS" has to be in section part, which is configured by openssl.conf file, so anyone met this problem has to put cps in that configure file, and tell openssl to search that part, like the code below:
bool AddX509ExtensionFromFile(X509* cert, X509* issuer, int nid, char* value,char* extFile)
{
if (extFile)
{
long errorline = -1;
X509V3_CTX ctx2;
CONF* extconf = NCONF_new(NULL);
if (!NCONF_load(extconf, extFile, &errorline))
{
if (errorline <= 0)
{
printf("NCONF_load error\n");
}
else
{
printf("error on line %ld of config file '%s'\n", errorline, extFile);
}
}
char* extsect = "default";
X509V3_set_ctx_test(&ctx2);
X509V3_set_nconf(&ctx2, extconf);
if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
{
printf("error loading extension section %s\n", extsect);
}
X509V3_set_ctx(&ctx2, issuer, cert, NULL, NULL, 0);
X509_EXTENSION* ex = X509V3_EXT_conf_nid(NULL, &ctx2, nid, value);
if (!ex) {
return false;
}
int result = X509_add_ext(cert, ex, -1);
X509_EXTENSION_free(ex);
return (result == 0) ? true : false;
}
return false;
}