1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
use std::fmt;

use crate::status::CdrPositionCapabilitiesList;
use crate::xfs::{
    method_response::XfsMethodResponse,
    params::{XfsParam, XfsParams},
};
use crate::{create_xfs_bool, create_xfs_i4, impl_xfs_struct, Error, Result};

mod anti_fishing_level;
mod cdr_type;
mod default_rollback_position;
mod euro_art6_capability;
mod recognition_sensor_type;
mod reporting_mode;
mod secured_comm_level;
mod self_test_mode;

pub use anti_fishing_level::*;
pub use cdr_type::*;
pub use default_rollback_position::*;
pub use euro_art6_capability::*;
pub use recognition_sensor_type::*;
pub use reporting_mode::*;
pub use secured_comm_level::*;
pub use self_test_mode::*;

create_xfs_bool!(
    AutoPresent,
    "autoPresent",
    r#"This specifies whether cash will be automatically presented to the user on execution of a dispense (autoPresent set to TRUE), or whether the cash will only be transported to the Bundler.

In the latter case, a [present](crate::cash::present) command will need to be issued following the [dispense](crate::cash::dispense) command.

Default value is FALSE.
"#
);
create_xfs_bool!(TrustedUser, "trustedUser", "Reserved for future use.");
create_xfs_i4!(
    MaxInBills,
    "maxInBills",
    "Maximum number of bills to be accepted by one command. Allways 1 for the BNR."
);
create_xfs_i4!(MaxOutBills, "maxOutBills", "Maximum number of bills to be dispensed by one command. Equals to 20 in BNA6 configuration, otherwise equals to 15.");
create_xfs_bool!(
    ShutterCmd,
    "shutterCmd",
    "The shutter be accessed by commands. Allways FALSE in the BNR."
);
create_xfs_bool!(Retract, "retract", "The cash dispenser can retract presented bills. Always TRUE in the BNR since FW v1.3.0, FALSE with previous versions.");
create_xfs_bool!(
    SafeDoorCmd,
    "safeDoorCmd",
    "This device supports a safe door command. Always FALSE in the BNR."
);
create_xfs_bool!(
    CashBox,
    "cashBox",
    "The service can handle a cash box. Always TRUE in the BNR."
);
create_xfs_bool!(Refill, "refill", "Can the BNR be refilled by placing bills of the same size on the stack of the Loader. Always TRUE in the BNR.");
create_xfs_bool!(Dispense, "dispense", "The device can dispense cash. Equals to FALSE in BNA6 configuration, otherwise equals to TRUE.");
create_xfs_bool!(
    Deposit,
    "deposit",
    "The device can deposit cash. Always TRUE in the BNR."
);
create_xfs_bool!(
    IntermediateStacker,
    "intermediateStacker",
    "The device has a temporary storage before presenting bills. Always TRUE in the BNR."
);
create_xfs_bool!(
    BillsTakenSensor,
    "billsTakenSensor",
    "The device has a bills taken sensor. Always TRUE in the BNR."
);
create_xfs_bool!(
    Escrow,
    "escrow",
    "The device supports an escrow. Always TRUE in the BNR."
);
create_xfs_i4!(EscrowSize, "escrowSize", "Specifies the maximum number of bills on the escrow. Equals to 20 in BNA6 configuration, otherwise equals to 15.");
create_xfs_bool!(
    Detector,
    "detector",
    "The device supports a detector to verify accepted cash. Always TRUE in the BNR."
);
create_xfs_bool!(
    AllowUsbFrontSwitch,
    "allowUsbFrontSwitch",
    "Allows to use USB Front interface to communicate with the BNR. Default value is TRUE."
);
create_xfs_bool!(ReportUsbConsumption, "reportUsbConsumption", "Specifies whether real max USB line consumption is reported on usb configuration descriptor instead of 0mA. Default value is FALSE.");
create_xfs_bool!(AutoRetractAtInlet, "autoRetractAtInlet", "Specifies whether bill will be automatically retracted to positioner when jam occurred during bill presenting at inlet or outlet. Default value is FALSE.");
create_xfs_bool!(RejectViaOutlet, "rejectViaOutlet", "Specifies whether measured but unknown or inhibited notes are rejected via the BNR’s Outlet instead of the Inlet. Default value is FALSE.");

/// Describes the BNR capabilities.
///
/// By default, capabilities are read-only properties, the following are writable:
///
/// - `auto_present`
/// - `self_test_mode`
/// - `anti_fishing_level`
/// - `allow_usb_front_switch`
/// - `reporting_mode`
/// - `report_usb_consumption`
/// - `auto_retract`
/// - `reject_via_outlet`
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct Capabilities {
    pub auto_present: AutoPresent,
    ///  Type of device. Always [CdrType::ATM](CdrType) for the BNR.
    pub cd_type: CdrType,
    /// Reserved for future use.
    pub euro_art6_capability: EuroArt6Capability,
    pub trusted_user: TrustedUser,
    pub max_in_bills: MaxInBills,
    pub max_out_bills: MaxOutBills,
    pub shutter_cmd: ShutterCmd,
    pub retract: Retract,
    pub safe_door_cmd: SafeDoorCmd,
    pub cash_box: CashBox,
    pub refill: Refill,
    pub dispense: Dispense,
    pub deposit: Deposit,
    pub intermediate_stacker: IntermediateStacker,
    pub bills_taken_sensor: BillsTakenSensor,
    pub escrow: Escrow,
    pub escrow_size: EscrowSize,
    pub detector: Detector,
    /// Specifies the default output position to rollback cash. Always [CdrPosition::Bottom](CdrPosition::Bottom) in the BNR.
    pub default_rollback_position: DefaultRollbackPosition,
    /// Specifies the capabilities of each position supported by the device. Please refer to [CdrPositionCapabilities] for default values.
    pub position_capabilities_list: CdrPositionCapabilitiesList,
    /// Allows to choose when the BNR can perform the self tests. Default value is [Auto](SelfTestMode::Auto) (recommended).
    pub self_test_mode: SelfTestMode,
    pub recognition_sensor_type: RecognitionSensorType,
    /// Sensitivity level of string detection at Inlet.
    /// Default value is [Normal](AntiFishingLevel::Normal).
    pub anti_fishing_level: AntiFishingLevel,
    pub allow_usb_front_switch: AllowUsbFrontSwitch,
    /// Specifies the kind of report generated on failure detection with no bill transported. Default value is [Normal](ReportingMode::Normal).
    pub reporting_mode: ReportingMode,
    pub report_usb_consumption: ReportUsbConsumption,
    pub auto_retract_at_inlet: AutoRetractAtInlet,
    pub reject_via_outlet: RejectViaOutlet,
    /// Indicates the security level in communication between Host and Bnr. Defaut value is [Level1](SecuredCommLevel::Level1).
    pub secured_comm_level: SecuredCommLevel,
}

impl Capabilities {
    /// Creates a new [Capabilities].
    pub const fn new() -> Self {
        Self {
            auto_present: AutoPresent::new(),
            cd_type: CdrType::Atm,
            euro_art6_capability: EuroArt6Capability::new(),
            trusted_user: TrustedUser::new(),
            max_in_bills: MaxInBills::create(1),
            max_out_bills: MaxOutBills::create(15),
            shutter_cmd: ShutterCmd::new(),
            retract: Retract::create(true),
            safe_door_cmd: SafeDoorCmd::new(),
            cash_box: CashBox::create(true),
            refill: Refill::create(true),
            dispense: Dispense::create(true),
            deposit: Deposit::create(true),
            intermediate_stacker: IntermediateStacker::create(true),
            bills_taken_sensor: BillsTakenSensor::create(true),
            escrow: Escrow::create(true),
            escrow_size: EscrowSize::create(15),
            detector: Detector::create(true),
            default_rollback_position: DefaultRollbackPosition::Bottom,
            position_capabilities_list: CdrPositionCapabilitiesList::new(),
            self_test_mode: SelfTestMode::new(),
            recognition_sensor_type: RecognitionSensorType::create(b'B'),
            anti_fishing_level: AntiFishingLevel::new(),
            allow_usb_front_switch: AllowUsbFrontSwitch::create(true),
            reporting_mode: ReportingMode::new(),
            report_usb_consumption: ReportUsbConsumption::new(),
            auto_retract_at_inlet: AutoRetractAtInlet::new(),
            reject_via_outlet: RejectViaOutlet::new(),
            secured_comm_level: SecuredCommLevel::new(),
        }
    }
}

impl From<&Capabilities> for XfsParam {
    fn from(val: &Capabilities) -> Self {
        Self::create(val.into())
    }
}

impl From<Capabilities> for XfsParam {
    fn from(val: Capabilities) -> Self {
        (&val).into()
    }
}

impl TryFrom<&XfsParam> for Capabilities {
    type Error = Error;

    fn try_from(val: &XfsParam) -> Result<Self> {
        val.value().try_into()
    }
}

impl TryFrom<XfsParam> for Capabilities {
    type Error = Error;

    fn try_from(val: XfsParam) -> Result<Self> {
        (&val).try_into()
    }
}

impl TryFrom<&XfsParams> for Capabilities {
    type Error = Error;

    fn try_from(val: &XfsParams) -> Result<Self> {
        val.params()
            .get(0)
            .ok_or(Error::Xfs(format!("Missing param: {val}")))?
            .inner()
            .value()
            .try_into()
    }
}

impl TryFrom<XfsParams> for Capabilities {
    type Error = Error;

    fn try_from(val: XfsParams) -> Result<Self> {
        (&val).try_into()
    }
}

impl TryFrom<&XfsMethodResponse> for Capabilities {
    type Error = Error;

    fn try_from(val: &XfsMethodResponse) -> Result<Self> {
        val.as_params()?.try_into()
    }
}

impl TryFrom<XfsMethodResponse> for Capabilities {
    type Error = Error;

    fn try_from(val: XfsMethodResponse) -> Result<Self> {
        (&val).try_into()
    }
}

impl fmt::Display for Capabilities {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{{")?;
        write!(f, r#""auto_present":{},"#, self.auto_present)?;
        write!(f, r#""cd_type":{},"#, self.cd_type)?;
        write!(
            f,
            r#""euro_art6_capability":{},"#,
            self.euro_art6_capability
        )?;
        write!(f, r#""trusted_user":{},"#, self.trusted_user)?;
        write!(f, r#""max_in_bills":{},"#, self.max_in_bills)?;
        write!(f, r#""max_out_bills":{},"#, self.max_out_bills)?;
        write!(f, r#""shutter_cmd":{},"#, self.shutter_cmd)?;
        write!(f, r#""retract":{},"#, self.retract)?;
        write!(f, r#""safe_door_cmd":{},"#, self.safe_door_cmd)?;
        write!(f, r#""cash_box":{},"#, self.cash_box)?;
        write!(f, r#""refill":{},"#, self.refill)?;
        write!(f, r#""dispense":{},"#, self.dispense)?;
        write!(f, r#""deposit":{},"#, self.deposit)?;
        write!(
            f,
            r#""intermediate_stacker":{},"#,
            self.intermediate_stacker
        )?;
        write!(f, r#""bills_taken_sensor":{},"#, self.bills_taken_sensor)?;
        write!(f, r#""escrow":{},"#, self.escrow)?;
        write!(f, r#""escrow_size":{},"#, self.escrow_size)?;
        write!(f, r#""detector":{},"#, self.detector)?;
        write!(
            f,
            r#""default_rollback_position":{},"#,
            self.default_rollback_position
        )?;
        write!(
            f,
            r#""position_capabilities_list":{},"#,
            self.position_capabilities_list
        )?;
        write!(f, r#""self_test_mode":{},"#, self.self_test_mode)?;
        write!(
            f,
            r#""recognition_sensor_type":{},"#,
            self.recognition_sensor_type
        )?;
        write!(f, r#""anti_fishing_level":{},"#, self.anti_fishing_level)?;
        write!(
            f,
            r#""allow_usb_front_switch":{},"#,
            self.allow_usb_front_switch
        )?;
        write!(f, r#""reporting_mode":{},"#, self.reporting_mode)?;
        write!(
            f,
            r#""report_usb_consumption":{},"#,
            self.report_usb_consumption
        )?;
        write!(
            f,
            r#""auto_retract_at_inlet":{},"#,
            self.auto_retract_at_inlet
        )?;
        write!(f, r#""reject_via_outlet":{},"#, self.reject_via_outlet)?;
        write!(f, r#""secured_comm_level":{}"#, self.secured_comm_level)?;
        write!(f, "}}")
    }
}

impl_xfs_struct!(
    Capabilities,
    "capabilities",
    [
        auto_present: AutoPresent,
        cd_type: CdrType,
        euro_art6_capability: EuroArt6Capability,
        trusted_user: TrustedUser,
        max_in_bills: MaxInBills,
        max_out_bills: MaxOutBills,
        shutter_cmd: ShutterCmd,
        retract: Retract,
        safe_door_cmd: SafeDoorCmd,
        cash_box: CashBox,
        refill: Refill,
        dispense: Dispense,
        deposit: Deposit,
        intermediate_stacker: IntermediateStacker,
        bills_taken_sensor: BillsTakenSensor,
        escrow: Escrow,
        escrow_size: EscrowSize,
        detector: Detector,
        default_rollback_position: DefaultRollbackPosition,
        position_capabilities_list: CdrPositionCapabilitiesList,
        self_test_mode: SelfTestMode,
        recognition_sensor_type: RecognitionSensorType,
        anti_fishing_level: AntiFishingLevel,
        allow_usb_front_switch: AllowUsbFrontSwitch,
        reporting_mode: ReportingMode,
        report_usb_consumption: ReportUsbConsumption,
        auto_retract_at_inlet: AutoRetractAtInlet,
        reject_via_outlet: RejectViaOutlet,
        secured_comm_level: SecuredCommLevel
    ]
);