package com.battery.device.bts;
|
|
import java.nio.file.Path;
|
import java.time.Duration;
|
import java.time.ZoneId;
|
import java.util.Map;
|
import com.battery.device.api.DeviceAdapter;
|
import com.battery.device.api.DeviceAdapterException;
|
import com.battery.device.api.credentials.LocalCredentials;
|
import com.battery.device.api.registry.AdapterInstanceConfig;
|
import com.battery.device.api.registry.DeviceAdapterFactory;
|
|
/**
|
* 按存储形态 {@code NEWARE_BTS} 构造**直连新威对外接口**的只读适配器实例(ADR-0068)。
|
*
|
* <p>与 {@code NEWARE_MYSQL}(直连厂商库)并列:这台机器能不能远程取数,取决于它的上位机形态,
|
* 而不是厂商。8.0 形态的库内没有逐点数据,所以它的逐点只能从接口的 {@code download} 取。
|
*
|
* <p><b>为什么口令不进数据库</b>:这里要的是那台机器的**本地管理员口令**——它和厂商库口令一样是来源凭据,
|
* 因此共用同一套取值顺序(本地凭据文件 → 同名环境变量 → 同名 JVM 启动参数,见
|
* {@link LocalCredentials}),{@code source_config} 里只放变量名。三者都没有时装配失败,
|
* 错误信息同时点名文件路径与变量名,使"忘了放口令"是可见的失败而不是沉默的缺失。
|
*
|
* <p>本类不缓存实例:实例由 {@code DeviceAdapterRegistry} 持有并按实例串行执行。
|
*/
|
public final class NewareBtsAdapterFactory implements DeviceAdapterFactory
|
{
|
/** 实例配置里承载"本机管理员账号变量名"的键。 */
|
public static final String USER_ENV_OPTION = "userEnv";
|
/** 实例配置里承载"本机管理员口令变量名"的键。 */
|
public static final String PASSWORD_ENV_OPTION = "passwordEnv";
|
public static final String DEFAULT_USER_ENV = "NEWARE_WIN_USER";
|
/** 建 SMB 会话是本地进程操作,超时给短一些:卡住也没有数据可取。 */
|
private static final Duration SESSION_TIMEOUT = Duration.ofSeconds(10);
|
/** 读应答超时;{@code download} 一页上千行在 SMB 上会慢一些,但远不到这个量级。 */
|
private static final Duration RESPONSE_TIMEOUT = Duration.ofSeconds(60);
|
/** 凭据文件相对进程工作目录定位,使开发(仓库根)与交付(应用目录)用同一个位置。 */
|
static final Path CREDENTIALS_FILE = LocalCredentials.DEFAULT_FILE;
|
|
/** 返回本形态的适配器类型标识 {@code NEWARE_BTS}。 */
|
@Override
|
public String adapterType()
|
{
|
return NewareBtsAdapter.ADAPTER_TYPE;
|
}
|
|
/** 从实例配置取账号与口令来源,装配远程命名管道传输与报文编解码器。 */
|
@Override
|
public DeviceAdapter create(AdapterInstanceConfig config)
|
{
|
Map<String, String> sourceConfig = config.sourceConfig();
|
String user = LocalCredentials.resolve(option(sourceConfig, USER_ENV_OPTION, DEFAULT_USER_ENV),
|
CREDENTIALS_FILE.toAbsolutePath(), System.getenv(), System::getProperty);
|
String password = LocalCredentials.resolve(required(sourceConfig, PASSWORD_ENV_OPTION),
|
CREDENTIALS_FILE.toAbsolutePath(), System.getenv(), System::getProperty);
|
NewareBtsPipeTransport transport = new NewareBtsPipeTransport(config.host(), user, password,
|
SESSION_TIMEOUT, RESPONSE_TIMEOUT);
|
return new NewareBtsAdapter(config.adapterCode(), transport,
|
new BtsXmlCodec(config.adapterCode(), ZoneId.of(config.timezoneId())), config.capabilities());
|
}
|
|
private static String option(Map<String, String> sourceConfig, String key, String fallback)
|
{
|
String value = sourceConfig.get(key);
|
return value == null || value.isBlank() ? fallback : value.trim();
|
}
|
|
/** 口令变量名没有缺省值:五台机器的口令实测有两种,猜一个就会连错机器。 */
|
private static String required(Map<String, String> sourceConfig, String key)
|
{
|
String value = option(sourceConfig, key, null);
|
if (value == null) throw new DeviceAdapterException("新威 BTS 实例缺少配置项 " + key
|
+ "(本机管理员口令的变量名):口令有两种取值,不能有缺省");
|
return value;
|
}
|
}
|